Back

Tips and Tricks for Debugging GitHub Actions

Tips and Tricks for Debugging GitHub Actions

A workflow that passed yesterday now fails with a cryptic error. You haven’t changed anything. The logs show a wall of collapsed steps, and somewhere in there lies the actual problem. This scenario frustrates every engineer who maintains CI/CD pipelines.

Effective GitHub Actions debugging requires knowing which tools exist and when to use them. This guide covers the stable, evergreen techniques that help you diagnose workflow failures quickly—without wasting time on approaches that won’t work.

Key Takeaways

  • Enable debug logging with ACTIONS_STEP_DEBUG and ACTIONS_RUNNER_DEBUG secrets for deeper visibility into workflow failures
  • Add diagnostic steps to output environment details and use continue-on-error: true temporarily to isolate flaky steps
  • Validate workflows locally with actionlint and nektos/act before pushing to catch errors early
  • Pin action versions to specific tags or SHAs to prevent unexpected breakages from upstream changes

Enable Debug Logging for Deeper Visibility

When standard GitHub Actions logs don’t reveal enough detail, enable debug logging. Two repository secrets control this behavior:

  • ACTIONS_STEP_DEBUG: Set to true to see verbose output for each step
  • ACTIONS_RUNNER_DEBUG: Set to true for runner-level diagnostic information

You can also trigger debug mode without modifying secrets. When re-running a failed workflow, select “Re-run jobs” and check the “Enable debug logging” option. This provides detailed traces for that specific run without affecting future executions.

GitHub’s log viewer supports live streaming and expanded recent log display, making it easier to follow long-running jobs in real time. Use the search function within expanded steps to locate specific errors rather than scrolling through everything.

Add Diagnostic Steps to Your Workflow

Sometimes you need custom debugging information. Add steps that output environment details before critical operations:

- name: Debug environment
  run: |
    echo "Node version: $(node --version)"
    echo "Working directory: $(pwd)"
    echo "Event: ${{ github.event_name }}"
    env | sort

For steps that fail unpredictably, use continue-on-error: true temporarily. This lets subsequent steps run, exposing whether the failure cascades or remains isolated:

- name: Potentially flaky step
  id: tests
  continue-on-error: true
  run: npm test

- name: Capture state after tests
  if: always()
  run: echo "Tests completed with status ${{ steps.tests.outcome }}"

Remove continue-on-error once you’ve identified the root cause.

Validate Workflows Locally Before Pushing

Pushing commits just to test workflow syntax wastes time and clutters your history. Use actionlint to catch YAML errors and expression mistakes before they reach GitHub:

actionlint .github/workflows/

For more comprehensive local testing, nektos/act runs workflows in Docker containers that approximate GitHub’s runner environment. It won’t replicate everything—artifact retention and exact software versions differ—but it validates step execution order and catches obvious configuration problems.

act -P ubuntu-latest=catthehacker/ubuntu:act-latest

Both tools provide fast feedback loops that reduce workflow troubleshooting cycles significantly.

Understand Artifact Behavior

Artifacts in GitHub Actions are job-scoped. Multiple jobs cannot upload to the same artifact name under the v4 system—attempts will conflict rather than merge. Always give each job a unique artifact name, especially in matrix or parallel builds, to avoid upload failures and ensure predictable retrieval.

Use Reusable Workflows to Reduce Flakiness

Duplicated workflow logic across repositories introduces inconsistency. When the same steps exist in multiple places, debugging becomes harder because fixes must propagate everywhere.

Reusable workflows centralize common patterns. When you fix a bug or improve reliability in one place, all calling workflows benefit. This approach also makes CI/CD debugging easier to apply consistently across your organization.

Pin Action Versions and Avoid Deprecated Actions

Reference actions by SHA or specific version tags rather than @main or @master. Unpinned references can break workflows when upstream changes occur:

# Prefer this
uses: actions/checkout@v4

# Avoid this
uses: actions/checkout@main

Many older debug helper actions use deprecated Node.js versions. GitHub warns about these in workflow logs. Replace them with maintained alternatives to avoid unexpected failures when GitHub eventually removes support for legacy runtimes.

Protect Secrets in Debug Output

Debug logging exposes more information, which creates risk. Never echo secrets directly, even in debug steps. GitHub masks known secrets, but derived values or partial matches might leak. Review debug output before sharing logs publicly or in issue reports.

Conclusion

Workflow troubleshooting becomes manageable when you know the right techniques. Enable debug logging for visibility, add diagnostic steps strategically, validate locally with actionlint or act, and maintain consistency through reusable workflows. These GitHub Actions best practices apply regardless of how the platform evolves—they’re fundamentals that make CI/CD debugging faster and less frustrating.

FAQs

Random failures often stem from external dependencies changing, such as unpinned action versions updating, package registry issues, or rate limiting. Network timeouts and resource constraints on shared runners can also cause intermittent failures. Enable debug logging and check if the failure correlates with specific times or external service availability.

Use the steps context with the step's id attribute. First, assign an id to your step, then reference its outputs using the syntax steps.step_id.outputs.output_name. For the outcome of a step with continue-on-error, use steps.step_id.outcome which returns success, failure, cancelled, or skipped.

Yes. Use actionlint to validate YAML syntax and expressions locally. For more thorough testing, nektos/act runs workflows in Docker containers that simulate the GitHub runner environment. While act cannot replicate every GitHub feature, it catches most configuration errors and validates step execution order before you push.

ACTIONS_STEP_DEBUG enables verbose output for individual workflow steps, showing detailed information about each action's execution. ACTIONS_RUNNER_DEBUG provides lower-level diagnostic information about the runner itself, including environment setup and internal operations. For most debugging scenarios, ACTIONS_STEP_DEBUG provides sufficient detail.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay