{"record":{"id":"8fda9434e0621871","repo":"charmbracelet/crush","slug":"not-found","errorCode":null,"errorMessage":"not found","messagePattern":"not found","errorType":"exception","errorClass":"ErrNotFound","httpStatus":404,"severity":"error","filePath":"internal/client/errors.go","lineNumber":18,"sourceCode":"package client\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"slices\"\n)\n\n// Typed outcomes callers need to distinguish from ordinary transport\n// failures. Match them with errors.Is.\nvar (\n\t// ErrNotFound reports that the server answered 404. For a\n\t// workspace-scoped call this means the server no longer knows the\n\t// workspace — it was torn down, or the server was replaced under the\n\t// client — so the right response is to re-register rather than retry\n\t// the same ID, which can never start succeeding again.\n\tErrNotFound = errors.New(\"not found\")\n\n\t// ErrServerBusy reports that the server declined to shut down\n\t// because it is still hosting workspaces or is midway through\n\t// creating one. A client asking a version-mismatched server to stand\n\t// down must keep using it instead of assuming it is going away.\n\tErrServerBusy = errors.New(\"server busy\")\n\n\t// ErrServerShuttingDown reports that the server refused the request\n\t// because it has already committed to exiting. The work is not lost:\n\t// a replacement server can be started and the request retried\n\t// against it.\n\tErrServerShuttingDown = errors.New(\"server is shutting down\")\n\n\t// ErrUnsupported reports that the running server does not understand\n\t// the request because it predates the feature. Callers must decide\n\t// what is safe to do with an older server rather than treating the\n\t// failure as transient.\n\tErrUnsupported = errors.New(\"unsupported by the running server\")","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/errors.go#L1-L36","documentation":"ErrNotFound reports that the server answered 404. For a workspace-scoped call this means the server no longer knows the workspace — it was torn down, or the server was replaced under the client — so retrying the same ID can never start succeeding again. The client must re-register (create a new workspace) rather than retry.","triggerScenarios":"RetireClient receiving 404; checkStatus mapping http.StatusNotFound to this sentinel for any workspace-scoped call (SendMessage, attach, session ops); runSubscription's stream endpoint vanishing; AgentReadyErr surfacing a 404 while polling agent readiness.","commonSituations":"The server's idle shutdown replaced the process; detach grace expired and the workspace was torn down; workspace-scoped call issued against a restarted server that lost in-memory state.","solutions":["Re-register: create a new workspace instead of retrying the stale ID","Match with errors.Is(err, client.ErrNotFound) and branch to re-registration logic","Check whether the server process was replaced and reconnect to the current one"],"exampleFix":"// before\nif err := client.SendMessage(ctx, wsID, msg); err != nil { return err }\n// after\nif err := client.SendMessage(ctx, wsID, msg); err != nil {\n    if errors.Is(err, client.ErrNotFound) {\n        wsID, err = client.CreateWorkspace(ctx, path)\n        if err != nil { return err }\n        return client.SendMessage(ctx, wsID, msg)\n    }\n    return err\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":"func isErrNotFound(err error) bool {\n    return errors.Is(err, client.ErrNotFound)\n}","tryCatchPattern":"if err := client.SendMessage(ctx, wsID, msg); err != nil {\n    if errors.Is(err, client.ErrNotFound) {\n        return reRegisterAndResend(ctx, path, msg) // never retry the old ID\n    }\n    return err\n}","preventionTips":["Never retry a workspace-scoped call after 404 — the ID is permanently dead","Re-register (new workspace) on every ErrNotFound instead of backing off","Track server identity so a replaced server is detected before calls are made"],"tags":["http-404","workspace","retry"],"backgroundTag":"workspace-not-found","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}