{"record":{"id":"5cf4b2a28da22efd","repo":"charmbracelet/crush","slug":"server-busy","errorCode":null,"errorMessage":"server busy","messagePattern":"server busy","errorType":"exception","errorClass":"ErrServerBusy","httpStatus":null,"severity":"warning","filePath":"internal/client/errors.go","lineNumber":24,"sourceCode":"\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\")\n)\n\n// checkStatus returns nil when rsp's status code is one of ok\n// (http.StatusOK when none are given). Otherwise it returns an error\n// carrying the status code and, when the body decodes as a proto.Error,\n// the server-provided message. Statuses that callers act on are wrapped","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/errors.go#L6-L42","documentation":"ErrServerBusy reports that the server declined a shutdown request because it is still hosting workspaces or is midway through creating one. It corresponds to backend.ErrServerNotIdle on the wire. A client asking a version-mismatched server to stand down must keep using it instead of assuming it is going away.","triggerScenarios":"ShutdownServer or ShutdownServerIfIdle receiving a refusal from a server with live workspaces or an in-flight create; TestServer_RefusesShutdownWhileWorkspaceLive exercises exactly this condition.","commonSituations":"Version-mismatch handling that tries to shut a newer server down while other clients are attached; automation stopping a shared server during active sessions; create-grace window still open for a recently created workspace.","solutions":["Keep using the existing server — the refusal means it still has live work","Release all workspaces before retrying the shutdown","Only force-terminate if you control every attached client and can release them first"],"exampleFix":"// before\nerr := client.ShutdownServer(ctx)\nif err != nil { return err }\n// after\nerr := client.ShutdownServer(ctx)\nif errors.Is(err, client.ErrServerBusy) {\n    return nil // server still hosting live workspaces; keep using it\n}\nreturn err","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func isErrServerBusy(err error) bool {\n    return errors.Is(err, client.ErrServerBusy)\n}","tryCatchPattern":"err := client.ShutdownServerIfIdle(ctx)\nif errors.Is(err, client.ErrServerBusy) {\n    return nil // server still in use; continue working against it\n}\nreturn err","preventionTips":["Treat ErrServerBusy as 'do not shut down', not as a failure to escalate","Verify no other clients are attached before requesting shutdown","In version-mismatch flows, prefer using the running server over replacing it"],"tags":["shutdown","lifecycle","version-mismatch"],"backgroundTag":"server-not-idle","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}