Skip to content
Latchkey

Azure Pipelines Condition Always Skips a Job or Stage

A custom condition: replaces the implicit succeeded(). If you write a condition without including succeeded()/and(), or compare values of the wrong type, the job or stage is skipped (or runs when it should not).

What this error means

A job or stage with a custom condition is skipped even though upstream work passed, or it runs after a failure. The condition expression is silently evaluating to false (or true) for a reason that is easy to miss.

azure-pipelines.yml
# wrong: drops the implicit success check, so it runs even after failure
condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
# also wrong: compares a string to a boolean
condition: eq(variables.isPr, true)   # variables are strings -> use 'True'

Common causes

Custom condition drops succeeded()

Adding any condition: overrides the default succeeded(). Without and(succeeded(), ...) the stage may run after an upstream failure, or your boolean logic alone evaluates false and it skips.

Type mismatch in eq()

Pipeline variables are strings. eq(variables.x, true) compares a string to a boolean and is false; you need eq(variables.x, 'True') (note the string and casing).

How to fix it

Combine succeeded() with your check

Wrap the custom logic in and(succeeded(), ...) so the success gate is preserved.

azure-pipelines.yml
jobs:
  - job: deploy
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))

Compare against string values

Treat variables as strings in eq(), matching value and case.

azure-pipelines.yml
condition: and(succeeded(), eq(variables['System.PullRequest.IsFork'], 'False'))

How to prevent it

  • Always include succeeded() in a custom condition unless you intend otherwise.
  • Treat variables as strings ('True'/'False') in comparisons.
  • Use dependencies/stageDependencies outputs explicitly in conditions.

Frequently asked questions

What causes "Condition always skips"?
Adding any condition: overrides the default succeeded(). Without and(succeeded(), ...) the stage may run after an upstream failure, or your boolean logic alone evaluates false and it skips.
How do I fix Condition always skips?
Wrap the custom logic in and(succeeded(), ...) so the success gate is preserved.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card