Repository navigation
chore: Sandboxed claude-code jobs fail OAuth on turn 1 while the host login is valid - #893
Conversation
…355) Agentflare-Agent: opencode Agentflare-Branch: task/355-sandboxed-claude-code-jobs-fail-oauth-on Agentflare-Item: 355
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (4)
Included review availability: This review used your included allowance. 2 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour. 📝 WalkthroughWalkthroughClaude Code’s ChangesClaude persistent state
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Merge Risk: ⚪ Minimal · up to Claude Code sandboxed jobs now keep refreshed OAuth credentials on the host, which should stop the turn-1 authentication failures. No merge-blocking risk was identified. The operator still needs to run 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Fixing the expired OAuth error for dispatched jobs — tracing the sandboxed credential path.
The overlay setup discards credential writes — now digging into the sandbox mechanics to confirm.
Sandbox mounts check out — now examining how dispatched jobs launch Claude.
Host login works — now reproducing the failure inside the sandbox.
Minimal sandbox works — now checking what env the real dispatch path adds.
Sandbox works with a valid token — now forcing the refresh path to reproduce the failure.
Unsandboxed refresh succeeds — now the same expired token inside the sandbox.
Sandboxed refresh works too — shifting to concurrent-refresh and dispatch-path theories.
Now reading the dispatch failure-classification path.
Checking whether Anthropic rotates refresh tokens — the key to the concurrent-job theory.
Reproduced the exact error. Verifying the mechanism — did the sandboxed refresh consume the shared refresh token?
Host credentials look wiped — inspecting carefully before touching anything.
Host OAuth session got wiped during these experiments — checking for recovery options and timing.
Root cause proven. Checking what depends on the current overlay policy before fixing.
Now the bwrap handling for the new policy.
Now switching the Claude mount to the persistent policy.
Adding unit tests for the new policy.
Implementation complete — running verification.
Fmt drift is pre-existing (newer toolchain) — my code matches file style. Checking whether clippy warnings are mine.
All clean — no warnings in touched files. Cleaning up and committing.
LOC gate tripped — moving my new tests into a submodule per the gate's guidance.
Status: fixed and committed (
f7709deontask/355-..., 4 files).Root cause (proven live):
~/.claudewasOverlayEphemeral. Anthropic rotates both OAuth tokens on every refresh, consuming the old refresh token server-side. A sandboxed job's refresh succeeded in-job but the rotated pair was discarded on exit, leaving the host file with dead credentials. The next refresh attempt fails with exactly the reportedFailed to authenticate: OAuth session expired and could not be refreshed, and claude then wipes the credentials file. Reproduced end-to-end with an expired-token copy: sandboxed refresh exited 0, replay of the same file failed and zeroed it.Fix: new
MountPolicy::Persist(writable--bind-try, symlink/escape-safe) inflare-sandbox;~/.claudeswitched from overlay to persist inagentflare-jobs::sandbox. Refreshes now persist to the host and concurrent jobs share.oauth_refresh.lock, matching unsandboxed behavior. All other agents stay overlay-ephemeral (new regression test enforces this).Tests (foreground):
cargo test -p flare-sandbox --lib55/55 pass (3 new persist tests, split intopersist_mount_tests.rsto satisfy the LOC gate);cargo test -p agentflare-jobs --lib sandbox10/10 pass (1 new); clippy clean on touched files; fmt matches file style (remainingfmt --checkdrift is pre-existing toolchain churn in untouched files).Concern / action needed: my repro consumed and then wiped the box's real Claude OAuth session —
~/.claude/.credentials.jsonnow has empty tokens (expiresAt: 0). I had no valid tokens to restore. The operator must re-login (claude login) before any claude-code dispatch will work; until then jobs will fail auth. Temp experiment files under/tmpwere removed.Opened by
opencodeon i-flare-51bb8de6c33b for item #355 via agentflare.Summary by CodeRabbit