fix(oauth2): per-writer temp file for model-sync cache (concurrent-boot ENOENT)#54
fix(oauth2): per-writer temp file for model-sync cache (concurrent-boot ENOENT)#54stephane-segning wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Code Review
This pull request resolves a file-renaming race condition (ENOENT error) that occurs when multiple OpenCode instances boot concurrently and attempt to write to the same cache file. By updating both the opencode-models-info and opencode-oauth2 cache stores to use unique temporary file names suffixed with the process ID and a random UUID, concurrent writers no longer collide. Additionally, error handling was added to clean up orphaned temporary files on failure, and concurrent test cases were introduced to verify the fix. There are no review comments to evaluate, and I have no additional feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
…ot ENOENT) Several OpenCode instances booting at once (the desktop app restoring every project window in parallel) all ran the oauth2 model sync for the same provider and raced on a shared `<serverId>.json.tmp` temp file: one writer's atomic rename consumed the temp file another was about to rename, surfacing as `sync_failed … ENOENT … rename '*.json.tmp' -> '*.json'`. Temp files are now per-writer (pid + uuid) and unlinked on failure, so concurrent writers can't collide; rename stays atomic so last-writer-wins on the final path. Hardened the models-info FileCacheStore the same way (uuid + orphan cleanup) and added concurrent-write regression tests to both packages. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
3a0dba3 to
f7caade
Compare
What
Fixes a
sync_failed … ENOENT … rename '<serverId>.json.tmp' -> '<serverId>.json'error seen in a real desktop-app log.Root cause
The oauth2 model-sync cache writes atomically (write temp →
renameonto the real path) but used a shared temp name${filePath}.tmp. When several OpenCode instances boot at once — the desktop app restores every project window in parallel, each its own process — they all sync the same provider and race: process A'srenameconsumes the temp file process B just wrote, so B'srenamefails withENOENT.Impact is cosmetic-but-noisy: the winning writer's atomic write still lands (cache never corrupts), but the loser logs
ERROR sync_failedand falls back to a stale model list for that boot.Fix
opencode-oauth2saveServerState: per-writer temp name (pid+randomUUID()), with best-effortunlinkon failure so a failed write never strands an orphan temp file.renamestays atomic → last-writer-wins on the final path.opencode-models-infoFileCacheStore.put: hardened the same way (it already usedpid+Date.now(); addeduuidfor same-process/same-ms safety + orphan cleanup).Tests / docs
.tmpleftovers).CHANGELOG.mdUnreleased entry.docs/troubleshooting.md: a symptom-keyed entry for the ENOENT rename error.Pre-push gate (build + typecheck + test + lint + format:check) green.
🤖 Generated with Claude Code