devbox: self-heal stale cached ID on 404#333
Merged
Merged
Conversation
When the server GCs an idle devbox (30-day TTL), the cached ID in ~/.signadot/.devbox-id becomes stale and every subsequent CLI call fails or warns with a 404. GetID now treats 404 from GetDevbox or ClaimDevbox the same as a missing cache file: re-register and overwrite the file. In 'devbox list', a 404 on the cached ID is silently treated as absent (debug-only hint), since GetID will heal on the next operation that needs it. The explicit '--devbox <id>' path still errors on 404 rather than silently recreating. Fixes signadot/community#136 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
~/.signadot/.devbox-idbecomes stale when the server GCs an idle devbox (30-day TTL insandboxes/internal/control/devbox/constants.go). Every subsequent CLI call then warns or fails with a 404.devbox.GetIDnow treats a 404 fromGetDevboxorClaimDevboxthe same as a missing cache file: re-register and overwrite the file. Per-user devboxes recover transparently on the nextsignadot local connect.devbox listno longer prints the scary404 Not Found: no such devbox …warning when the cached ID is gone — it just omits the "current" row from the table. A--debughint identifies the cleared id for troubleshooting.signadot local connect --devbox <id>path is unchanged: a user-supplied ID still errors hard on 404 rather than silently recreating.Fixes signadot/community#136
Behavior trade-off
There's a competing use case where a platform team pre-registers a userless devbox on a Remote Dev Environment so multiple users share that RDE's local-connect session slots. Under that pattern, a loud failure when the pre-provisioned devbox vanishes would arguably be preferable to silently recreating one. We accept the trade-off because RDE devboxes very rarely sit 30 days idle without use, and the per-user case is hit constantly. If this pattern grows, the right follow-up is a config knob or devbox-metadata marker to opt into strict (no-auto-recreate) behavior.
Implementation notes
devbox.IsNotFound(err)predicate unwraps to*transport.APIError(not*runtime.APIError) —transport.FixAPIErrorsmiddleware in the SDK wraps every 4xx/5xx before the swagger reader sees it.registerAndPersisthelper centralizes the "register and write cache file" step, used both by the original file-not-exist path and the new 404-recovery sites.Test plan
Verified end-to-end against a local minikube + signadot install with apiserver backed by host MySQL:
signadot devbox register; confirm row in MySQL and matching~/.signadot/.devbox-id.DELETE FROM devboxes WHERE public_id=…;to simulate the GC step.signadot devbox list(no--debug): silent, no warning, table renders without the stale row.signadot --debug devbox list: printsdebug: cached devbox <id> is no longer registered.signadot local connect --unprivileged --wait=none --cluster=minikube: completes silently; cache file rewritten with a fresh valid id; session claimed.go build ./...andgo vet ./internal/devbox/... ./internal/command/devbox/... ./internal/command/local/...clean.🤖 Generated with Claude Code