ThisCalculator

Everyday

Stop Pipeline Agent Errors From Cascading

Updated · Standard formula, shown below

Stop Pipeline Agent Errors From Cascading

When a pipeline agent fails mid-run, the error often triggers a chain reaction: dependent jobs get skipped, artifacts go missing, and the whole run is marked failed even though the root cause was a single transient issue. This guide shows you how to isolate agent errors so they don’t cascade, using retry logic, conditional steps, and failure handling. You’ll learn practical techniques that work in most CI/CD systems like Jenkins, GitLab CI, GitHub Actions, and Azure Pipelines.

What You’ll Need

  • Access to your pipeline configuration file (e.g., .gitlab-ci.yml, Jenkinsfile, .github/workflows/*.yml, or azure-pipelines.yml).
  • Permission to edit and commit changes to the repository.
  • Basic understanding of your CI/CD system’s syntax (YAML or Groovy).
  • Ability to view pipeline logs and trigger test runs.

Step-by-Step

  1. Identify the exact agent error. Open the failed pipeline run and locate the job that first reported the error. Look for messages like “Agent lost connection,” “Unable to connect to agent,” “Timeout waiting for agent,” or “Agent is offline.” Note the job name and the step where it occurred.
  2. Add automatic retry for transient agent failures. Most CI systems have a built-in retry mechanism. For example, in GitLab CI, add retry: 2 to the job. In GitHub Actions, use jobs:<job_id>:steps:<step_id>:continue-on-error: true combined with a retry action. In Jenkins, wrap the step in a retry block: retry(3) { ... }. This handles temporary network blips or agent restarts.
  3. Mark the step as non-blocking with continue-on-error (GitHub Actions) or allow_failure (GitLab CI). If the agent error is in a non-critical step (like sending a notification or cleaning up), set this flag so the job continues even if that step fails. This prevents the error from failing the entire job.
  4. Use conditional execution to skip dependent steps. If a step depends on a previous step’s output (e.g., an artifact), add a condition like if: success() (GitHub Actions) or when: on_success (GitLab CI). This ensures that if the agent fails before producing the artifact, the dependent step is skipped rather than failing with a confusing “file not found” error.
  5. Isolate agent-heavy jobs into separate stages. Move jobs that are prone to agent issues (e.g., long-running tests, resource-intensive builds) into their own stage. If they fail, only that stage is marked failed, and later stages that don’t depend on them can still run.
  6. Set a timeout on agent-dependent steps. Add a timeout (e.g., timeout-minutes: 30 in GitHub Actions, timeout: 30m in GitLab CI). This prevents an agent hang from blocking the pipeline indefinitely, which often causes cascading timeouts in downstream jobs.
  7. Use a fallback agent pool or label. If your system supports multiple agent pools, configure the job to run on a fallback pool if the primary is unavailable. For example, in Azure Pipelines, you can use demands: Agent.OS -equals Linux and also specify a second pool in the job’s pool property.
  8. Cache dependencies to reduce agent load. If the agent error is due to resource exhaustion (e.g., out of memory), caching dependencies (like npm or pip packages) can reduce the agent’s workload and prevent failures. Use the built-in cache features in your CI system.
  9. Add a final always-run cleanup step. Use if: always() (GitHub Actions) or when: always (GitLab CI) for cleanup steps (e.g., stopping services, removing temp files). This ensures that even if the agent fails, the environment is reset, preventing stale states from affecting the next run.
  10. Monitor and alert on agent errors separately. Instead of failing the whole pipeline, send a notification (e.g., via webhook or email) when an agent error occurs. This way, you’re aware of the issue without blocking the release.

Common Mistakes

  • Retrying too many times. Setting retry: 5 or more can cause long delays and still fail. Stick to 2-3 retries.
  • Using continue-on-error on critical steps. This can mask real failures. Only use it for non-essential steps.
  • Not setting timeouts. Without a timeout, an agent hang can block the pipeline for hours, causing cascading failures in other jobs that are waiting.
  • Ignoring the root cause. Retrying a permanently broken agent (e.g., a misconfigured machine) will just fail again. Always check if the agent is healthy.

Tips

  • Test your retry logic by intentionally failing a step once to confirm it works.
  • Keep agent-specific configuration in a shared template or base job to avoid duplication.
  • Use pipeline-level concurrency limits to prevent too many jobs from hitting the same agent simultaneously.
  • Log the agent hostname or ID in your steps to help identify which agent is failing.
  • If your CI system supports it, use a “matrix” strategy to run the same job on multiple agents and accept if any succeeds.

Troubleshooting

If the error still cascades despite following the steps:

  • Check if the error is a true agent failure or a script error. Look at the log: if the agent disconnects mid-step, it’s an agent issue; if the script exits with a non-zero code, it’s a code issue. Adjust your retry/continue-on-error accordingly.
  • Verify that your retry syntax is correct. For example, in GitLab CI, retry: 2 must be at the job level, not the step level. In GitHub Actions, you need to use a third-party action for retries.
  • Check if the agent is actually offline. Sometimes the agent is fine, but a network firewall blocks the connection. Test by running a simple job on that agent.
  • Look at the pipeline’s dependency graph. If a job is marked as failed because its upstream job failed, but the upstream job was actually skipped, you may need to change the condition from success() to !cancelled() to allow the downstream job to run.
  • If using a self-hosted agent, ensure it’s updated. An outdated agent can cause connection issues. Update the agent software and restart the service.

Frequently Asked Questions

Why does one agent error fail the entire pipeline?

By default, most CI systems treat any job failure as a pipeline failure. When a job fails, all downstream jobs that depend on it are also marked as failed, even if they didn’t run. This is the cascading effect.

Can I retry only the failed step, not the whole job?

In some systems like GitHub Actions, you can use a retry action around a specific step. In GitLab CI, retry is at the job level, so the entire job reruns. For step-level retry, you’d need to script it yourself (e.g., a bash loop).

What’s the difference between continue-on-error and allow_failure?

They are similar but in different systems. continue-on-error is GitHub Actions; allow_failure is GitLab CI. Both mark the job as successful even if it fails, so the pipeline continues. However, in GitLab, the job is shown as “passed with warnings” if it fails with allow_failure.

How do I prevent a failed agent from affecting the next run?

Ensure your cleanup steps run with if: always() or when: always. Also, consider using ephemeral agents (like containers) that are destroyed after each job, so no state persists.

Should I use a retry for all agent errors?

No. Retry is only useful for transient errors (e.g., network timeouts, agent restarts). If the error is due to a misconfigured agent or a permanent resource issue, retrying will just waste time. Check the error message first.

Can I set a global retry policy for all jobs?

Yes, in many systems you can define a default retry at the pipeline level. For example, in GitLab CI, you can set default: retry: 2. In GitHub Actions, you’d need to use a composite action or a workflow-level default, but it’s not as straightforward.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.