Skip to content

Error Reference

Every failure path writes error-code, error-message, and, when a response arrived, http-status. Branch on error-code rather than parsing log text. Reading these outputs requires continue-on-error: true on the step, because the action exits with status 1 on failure.

error-code carries values from two sources.

  • Codes prefixed with action_ come from the action itself. They describe failures that never reached the server, plus responses the action could not interpret.
  • Every other value is the code field from the server’s own error body, passed through unchanged.

Action codes

error-codehttp-statusCauseFix
action_invalid_inputemptyAn input is missing or fails validation. Raised before any network call.Check the value against the rules in Inputs and Outputs.
action_missing_oidc_envemptyACTIONS_ID_TOKEN_REQUEST_TOKEN or ACTIONS_ID_TOKEN_REQUEST_URL is unset.Add permissions: id-token: write to the job.
action_oidc_fetch_failedemptyGitHub Actions did not return an OIDC token, or returned a body with no value field.Usually transient. Re-run the job, then check the GitHub Actions status page.
action_connection_failedstatus of the last attempt, when one was receivedThe server could not be reached after four attempts, and the last response body was not a github-sts error object.Verify sts-url resolves and is reachable from the runner.
action_invalid_response200The server returned success with no token field.Check the server logs. A 200 without a token indicates a server-side defect.
action_malformed_error_responsethe response statusThe server returned an error whose body had no string code field.Check the server version and logs. The error contract may have changed.
action_internal_erroremptyAn unexpected exception inside the action.Read the full step log and open an issue against the action.

Server codes

Any other value of error-code is the server’s own code, forwarded exactly as received. The authoritative list, with the HTTP status attached to each code, is the API Reference error table. Codes such as policy_denied, audience_mismatch, policy_not_found, and replay_detected reach your workflow unchanged.

The action does not maintain a copy of that list. A code added by a newer server release passes through without an action release.

How server codes reach the output

Two paths write a server code.

  1. The response is not retryable, that is any status below 500. The action reads the body, takes code, and writes it directly.
  2. The response is a 5xx and every retry produced the same failure. The action then parses the body of the final attempt. If it carries a code, that value is written; otherwise the code becomes action_connection_failed.

The second path matters for deterministic 5xx codes. A 502 with upstream_error, raised when the trust policy grants a permission the GitHub App does not hold, is retried four times before it surfaces. The step takes several seconds longer than a 403 denial does.

Interpreting the error message

error-message is built from the HTTP status and the detail field of the response body.

StatusMessage prefix
400Configuration error:
401OIDC token validation failed:
403Trust policy denied the request:
404Trust policy not found:
409Token replay detected:
any otherSTS server error (HTTP {status}):

The message is for humans. Its wording is not a stable interface. Branch on error-code.

Branching on the failure

      - uses: Depthmark/github-sts-action@v0.2.0
        id: sts
        continue-on-error: true
        with:
          sts-url: ${{ vars.STS_URL }}
          audience: https://sts.example.com
          scope: my-org/my-repo
          identity: ci

      - name: Handle the result
        run: |
          case "${{ steps.sts.outputs.error-code }}" in
            "")
              echo "Token issued" ;;
            replay_detected)
              echo "Transient: another job consumed this OIDC token, re-run" ;;
            policy_denied|audience_mismatch)
              echo "::error::Trust policy rejected this workflow: ${{ steps.sts.outputs.error-message }}"
              exit 1 ;;
            *)
              echo "::error::${{ steps.sts.outputs.error-code }}: ${{ steps.sts.outputs.error-message }}"
              exit 1 ;;
          esac

For diagnosing a denial from the server side, including the trace_id correlation, see Troubleshooting.