{"record":{"id":"fd21a65206db7cba","repo":"charmbracelet/crush","slug":"failed-to-check-project-init-status-code-d","errorCode":null,"errorMessage":"failed to check project init: status code %d","messagePattern":"failed to check project init: status code (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/config.go","lineNumber":174,"sourceCode":"\t\treturn fmt.Errorf(\"failed to refresh OAuth token: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to refresh OAuth token: status code %d\", rsp.StatusCode)\n\t}\n\treturn nil\n}\n\n// ProjectNeedsInitialization checks if the project needs\n// initialization.\nfunc (c *Client) ProjectNeedsInitialization(ctx context.Context, id string) (bool, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/project/needs-init\", id), nil, nil)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"failed to check project init: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn false, fmt.Errorf(\"failed to check project init: status code %d\", rsp.StatusCode)\n\t}\n\tvar result struct {\n\t\tNeedsInit bool `json:\"needs_init\"`\n\t}\n\tif err := json.NewDecoder(rsp.Body).Decode(&result); err != nil {\n\t\treturn false, fmt.Errorf(\"failed to decode project init response: %w\", err)\n\t}\n\treturn result.NeedsInit, nil\n}\n\n// MarkProjectInitialized marks the project as initialized on the\n// server.\nfunc (c *Client) MarkProjectInitialized(ctx context.Context, id string) error {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/project/init\", id), nil, nil, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to mark project initialized: %w\", err)\n\t}\n\tdefer rsp.Body.Close()","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/config.go#L156-L192","documentation":"ProjectNeedsInitialization only treats HTTP 200 as success; any other status yields this error. The server was reached but rejected the needs-init query, so the client cannot report initialization state.","triggerScenarios":"Calling ProjectNeedsInitialization and the server returns non-200: 401/403 for unauthorized workspace access, 404 when the workspace id does not exist, or 5xx server error.","commonSituations":"Stale workspace id after the server database was reset; expired auth token in the client; querying a workspace deleted by another user; server regression deploying a broken needs-init endpoint.","solutions":["Check the numeric status in the message: 401/403 means re-authenticate, 404 means the workspace id is wrong or deleted","Verify the workspace was created and the id is current","Check server logs and health for 5xx before retrying","Refresh the client's credentials if auth recently expired"],"exampleFix":"// before\nneedsInit, err := client.ProjectNeedsInitialization(ctx, id)\nif err != nil {\n    return err\n}\n// after\nneedsInit, err := client.ProjectNeedsInitialization(ctx, id)\nif err != nil {\n    if strings.Contains(err.Error(), \"status code 404\") {\n        return ErrWorkspaceNotFound\n    }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"// Validate the workspace exists first\nworkspaces, err := client.ListWorkspaces(ctx)\nif err != nil {\n    return err\n}\nexists := false\nfor _, w := range workspaces {\n    if w.ID == id {\n        exists = true\n    }\n}\nif !exists {\n    return fmt.Errorf(\"workspace %s does not exist\", id)\n}","typeGuard":"func isStatusError(err error, code int) bool {\n    return err != nil && strings.Contains(err.Error(), fmt.Sprintf(\"status code %d\", code))\n}","tryCatchPattern":"needsInit, err := c.ProjectNeedsInitialization(ctx, id)\nif err != nil {\n    if isStatusError(err, 404) {\n        return ErrWorkspaceNotFound\n    }\n    if isStatusError(err, 401) {\n        return reauthenticateAndRetry(ctx)\n    }\n    return err\n}","preventionTips":["Refresh auth tokens before they expire to avoid 401/403 on bootstrap checks","Validate workspace ids against a list call before status queries","Do not blanket-retry 4xx statuses; only retry 429/5xx","Keep client and server versions aligned on the needs-init endpoint"],"tags":["http-client","http-status","bootstrap"],"backgroundTag":"unexpected-http-status","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}