Skip to main content

Why my Azure DevOps scheduled pipeline never ran

I set up a scheduled pipeline in Azure DevOps. The YAML was valid. No errors on save. I waited patiently for the cron to fire.

Nothing happened…

The culprit turned out to be a single line I'd added for a completely legitimate reason trigger: none.

The setup

The pipeline looked roughly like this:

trigger: none

schedules:
  - cron: "0 2 * * 1-5"
    displayName: Nightly weekday build
    branches:
      include:
        - main
    always: true

The intent was straightforward: I didn't want CI runs on every push, so I explicitly disabled that with trigger: none. And I wanted the pipeline to run on a schedule. Seems fine, right?

Except it never ran.

What's actually happening

Here's the thing that isn't obvious until you read the docs carefully (or waste an afternoon debugging): in Azure DevOps YAML pipelines, trigger is specifically the CI trigger — the thing that fires on code pushes. schedules is a completely separate concept.

So when I wrote trigger: none, I was trying to tell Azure DevOps: "don't fire on commits." That's it. I expected schedules to happily do its own thing in parallel.

But it didn’t.

When trigger: none is present, Azure DevOps suppresses scheduled runs as well. The schedule is defined, it validates fine, it even shows up if you look at the pipeline configuration — but the runs simply don't happen.

There's no warning. No error. No notification. Just silence.

The fix

Remove trigger: none. That's it.

If you don't want CI triggers firing on every push, but you do want scheduled runs, the correct approach is to either:

Option A — Let the default CI trigger stand, but scope it narrowly:

trigger:
  branches:
    include:
      - none  # effectively disables CI without using trigger: none

schedules:
  - cron: "0 2 * * 1-5"
    displayName: Nightly weekday build
    branches:
      include:
        - main
    always: true

Option B — Just remove trigger: entirely if this is a schedule-only pipeline:

schedules:
  - cron: "0 2 * * 1-5"
    displayName: Nightly weekday build
    branches:
      include:
        - main
    always: true

Without an explicit trigger: section, Azure DevOps applies the default CI behavior (trigger on all branches), unless your organization has the "Disable implied YAML CI trigger" setting enabled at org or project level. If you're worried about that, scope the CI trigger explicitly to a non-existent branch, or check your org settings.

Why I find this confusing?

Because the mental model I had is: "these are independent trigger types, and I can configure them independently." That's true in many CI systems. In Azure DevOps YAML, trigger: none is a broader hammer than it looks.

The official documentation does document this, but it's easy to miss if you're just looking to disable CI triggers and move on.

Other gotchas while we are here

If your scheduled pipeline still isn't running after removing trigger: none, check these:

UI-defined schedules override YAML schedules. If you ever configured a schedule through the pipeline settings UI, that takes precedence over everything you define in YAML. Only UI-defined schedules will run, and you'll need to delete them through the UI (then trigger a new push) before your YAML schedules take effect.

The schedule is evaluated per branch. A schedule only applies to branches explicitly listed in the branches.include section. If you're targeting main but your YAML changes are on a feature branch, the schedule for main is based on the last committed YAML on main. Changes on other branches don't update the schedule for main.

always: true matters. By default, Azure DevOps won't run a scheduled build if there have been no code changes since the last successful run. Set always: true if you want the pipeline to run regardless.

Verify with Scheduled Runs view. In the Azure DevOps UI, go to your pipeline and select "Scheduled runs" from the ... menu. This shows you the next few upcoming runs. If nothing shows there, your schedule isn't being picked up — regardless of what's in your YAML.

TL;DR

trigger: none doesn't just disable CI triggers — it disables scheduled runs too. If you want a schedule-only pipeline, remove the trigger: key entirely, or scope the CI trigger to something that won't match.

One line. No validation error. Hours of head-scratching.

More information

Triggers in Azure Pipelines - Azure Pipelines | Microsoft Learn

Popular posts from this blog

Podman– Command execution failed with exit code 125

After updating WSL on one of the developer machines, Podman failed to work. When we took a look through Podman Desktop, we noticed that Podman had stopped running and returned the following error message: Error: Command execution failed with exit code 125 Here are the steps we tried to fix the issue: We started by running podman info to get some extra details on what could be wrong: >podman info OS: windows/amd64 provider: wsl version: 5.3.1 Cannot connect to Podman. Please verify your connection to the Linux system using `podman system connection list`, or try `podman machine init` and `podman machine start` to manage a new Linux VM Error: unable to connect to Podman socket: failed to connect: dial tcp 127.0.0.1:2655: connectex: No connection could be made because the target machine actively refused it. That makes sense as the podman VM was not running. Let’s check the VM: >podman machine list NAME         ...

Azure DevOps/ GitHub emoji

I’m really bad at remembering emoji’s. So here is cheat sheet with all emoji’s that can be used in tools that support the github emoji markdown markup: All credits go to rcaviers who created this list.

VS Code Planning mode

After the introduction of Plan mode in Visual Studio , it now also found its way into VS Code. Planning mode, or as I like to call it 'Hannibal mode', extends GitHub Copilot's Agent Mode capabilities to handle larger, multi-step coding tasks with a structured approach. Instead of jumping straight into code generation, Planning mode creates a detailed execution plan. If you want more details, have a look at my previous post . Putting plan mode into action VS Code takes a different approach compared to Visual Studio when using plan mode. Instead of a configuration setting that you can activate but have limited control over, planning is available as a separate chat mode/agent: I like this approach better than how Visual Studio does it as you have explicit control when plan mode is activated. Instead of immediately diving into execution, the plan agent creates a plan and asks some follow up questions: You can further edit the plan by clicking on ‘Open in Editor’: ...