GitHub Actions Debugging and Troubleshooting

Workflows fail for many reasons — typos in YAML, wrong file paths, expired secrets, race conditions, and flaky tests. Knowing how to diagnose and fix problems quickly saves hours of frustration. This topic gives you a systematic toolkit for debugging any GitHub Actions workflow.

Reading Workflow Logs

The Actions tab in your repository shows the output of every workflow run. Click a run, then click a job, then expand any step to see its full log output.

Repository → Actions tab
                │
                └── Workflow run (click to open)
                        │
                        ├── build job (click to open)
                        │   ├── ▶ Set up job
                        │   ├── ▶ Run actions/checkout@v4
                        │   ├── ▶ Install dependencies   ← Click to expand
                        │   └── ▶ Run tests              ← Red = failed step
                        │
                        └── deploy job (skipped)

A red X marks the step that failed. The log output beneath it shows the exact error message. Start here — most failures have a clear error message that points directly to the fix.

Enabling Debug Logging

When log output is not enough, enable debug mode to get verbose output from every step and action.

Method 1: Repository Secret

Add a secret named ACTIONS_STEP_DEBUG with the value true. All subsequent runs in that repository produce debug output.

Method 2: Re-run with debug logging

In the Actions tab, click a failed run, then click the Re-run jobs button and choose Enable debug logging. This adds debug output for that single re-run only without touching your secrets.

Debug mode reveals:
  - Exact values of expressions and contexts
  - Step pre/post processing details
  - Tool download and installation logs
  - File system state at each step
  - Network calls made by actions

Adding Debug Steps to Your Workflow

Insert temporary diagnostic steps when you need to understand what the runner sees at a specific point:

steps:
  - uses: actions/checkout@v4

  - name: Debug — show working directory contents
    run: ls -la

  - name: Debug — show all environment variables
    run: env | sort

  - name: Debug — show git status
    run: git log --oneline -5

  - name: Debug — show disk space
    run: df -h

  - name: Debug — show current user
    run: whoami && id

Remove these steps once the issue is resolved. Printing environment variables in logs can expose non-secret configuration values you might prefer to keep private.

Using tmate for Interactive Debugging

The mxschmitt/action-tmate action pauses the workflow and opens a live SSH session into the runner. You can then run commands manually to investigate the environment:

steps:
  - uses: actions/checkout@v4
  - run: npm ci

  - name: Open SSH session for debugging
    uses: mxschmitt/action-tmate@v3
    if: failure()       ← Only opens when a previous step fails

When the workflow hits the tmate step, it prints a connection command in the logs. You connect via your terminal, poke around the runner, and then press q in the tmate session to let the workflow continue.

Always add if: failure() so the session only opens when something goes wrong. Remove this step before merging to your main branch — leaving it active would make every failed run pause indefinitely and consume runner minutes.

Common Failures and Their Fixes

YAML Indentation Errors

Error: "You have an error in your yaml syntax"

Cause: Wrong indentation or a tab character mixed with spaces.

Fix: Use a YAML linter. Install the GitHub Actions extension
     for VS Code — it highlights YAML errors as you type.
     Always use 2 spaces per indent level, never tabs.

Action Not Found

Error: "Can't find 'action.yml' ... for action 'my-org/my-action'"

Cause 1: The action path is wrong.
Cause 2: The version tag does not exist.
Cause 3: The repository is private and the workflow has no access.

Fix: Verify the action name and version on GitHub Marketplace.
     Check the exact tag name in the action's repository.

Secret Not Set

Error: Command fails with "unauthorized" or "permission denied"

Cause: The secret referenced in the workflow does not exist,
       or is set in the wrong scope.

Fix: Go to Settings → Secrets → Actions and confirm the
     secret name matches exactly (case-sensitive).
     Check whether it is a repository secret or environment secret.

File Not Found After Checkout

Error: "No such file or directory: ./dist/app.js"

Cause: The file was generated in a previous job but not uploaded
       as an artifact. Runner machines do not share a file system.

Fix: Upload the file as an artifact in the producing job.
     Download it in the consuming job before using it.

Permission Denied on Script

Error: "Permission denied: ./deploy.sh"

Cause: The shell script is not executable on the runner.

Fix: Add this step before running the script:
     - run: chmod +x ./deploy.sh

     Or commit the file with execute permissions:
     git add --chmod=+x deploy.sh && git commit -m "Make executable"

Cache Miss Every Run

Symptom: Cache never hits, reinstalling packages every run.

Cause 1: The cache key changes every run because the lockfile
         path is wrong or the file keeps changing.

Cause 2: The path being cached does not match where packages
         are actually installed.

Fix: Print the key: run: echo "${{ hashFiles('package-lock.json') }}"
     Confirm the hash is stable between runs.
     Verify the cache path matches the actual package directory.

Checking Workflow Syntax Before Pushing

Validate your YAML locally before pushing to avoid slow feedback loops:

Option 1: VS Code extension
  Install "GitHub Actions" extension
  Red underlines show errors as you type

Option 2: actionlint CLI tool
  npm install -g @github/actionlint
  actionlint .github/workflows/ci.yml

Option 3: GitHub's web editor
  Edit the file directly on github.com/your-repo
  The editor validates YAML and shows suggestions inline

Workflow Run History and Re-Runs

GitHub keeps the last 90 days of workflow run history. From the Actions tab you can:

  • Re-run a failed workflow with one click (saves time — reruns only failed jobs)
  • Download logs as a zip archive for offline analysis
  • View which commit and branch triggered each run
  • See the exact duration and cost (in minutes) of each run

Systematic Debugging Checklist

Step 1: Read the failed step log — what does the error say?
Step 2: Check environment — is the expected tool/file present?
Step 3: Check secrets — are all required secrets set correctly?
Step 4: Enable debug logging — re-run with debug enabled
Step 5: Add diagnostic steps — print env, ls, cat relevant files
Step 6: Use tmate — open an interactive shell if still stuck
Step 7: Simplify — comment out steps until the issue is isolated
Step 8: Search GitHub Issues — others have likely hit the same error

Leave a Comment

Your email address will not be published. Required fields are marked *