anthropics / anthropics/claude-code-action
retryWithBackoff: non-retryable intent in github-file-ops-server.ts is unenforced
- Dominant language
- TypeScript
- Stars
- 8.9k
- Forks
- 2.1k
- Avg merge
- 3d 9h
- Merged PRs (30d)
- 10
Description
## Summary
`github-file-ops-server.ts` contains two `retryWithBackoff` call sites (around lines 373 and 588, both in `updateRef`) with comments that say:
```
// For non-403 errors, fail immediately without retry
console.error("Non-retryable error:", updateRefResponse.status);
throw error;
```
However, throwing from inside the operation lambda does **not** prevent `retryWithBackoff` from retrying — the function catches all errors unconditionally. So the "fail immediately" intent is silently ignored and the error is retried up to 3 times (with 5–20s backoff) regardless.
## Impact
- 400 Bad Request, 404 Not Found, 422 Unprocessable Entity on git ref updates are retried despite being deterministic failures
- Each deterministic failure wastes ~35 seconds of wall time before the action reports an error
- The misleading comments create a false impression that retry behavior is already controlled at these call sites
## Relation to #1081
This is related to #1081 (which addresses `WorkflowValidationSkipError` retries in `token.ts`). Once #1081's fix lands, the `NonRetryable` marker interface (`src/utils/errors.ts`) will be available to classify errors at these call sites too.
## Suggested fix
After #1081 is resolved, create an `HttpError` class that implements `NonRetryable` for non-retryable 4xx status codes (400, 401, 403, 404, 422), then throw `HttpError` from the two `updateRef` call sites instead of a plain `Error`. The `retryWithBackoff` default will automatically skip retries for any `NonRetryable` error.
Alternatively, pass an explicit `shouldRetry` option at these call sites that checks the HTTP status.
## Files
- `src/mcp/github-file-ops-server.ts` — two `updateRef` call sites
Contributor guide
Research direction
Start with the two updateRef retryWithBackoff call sites in src/mcp/github-file-ops-server.ts, then read the retry behavior and the NonRetryable marker in src/utils/errors.ts. Review the dependency on #1081 and choose one of the stated approaches; done means deterministic 4xx ref-update failures return immediately while retryable errors retain their retries.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100