{"record":{"id":"f6a0772ec311cd38","repo":"charmbracelet/crush","slug":"failed-to-run-shell-command-status-code-d","errorCode":null,"errorMessage":"failed to run shell command: status code %d","messagePattern":"failed to run shell command: status code (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":537,"sourceCode":"\tvar e proto.Error\n\tif err := json.NewDecoder(body).Decode(&e); err != nil {\n\t\treturn \"\"\n\t}\n\treturn e.Message\n}\n\n// RunShellCommand runs a shell command in the workspace without triggering the agent.\nfunc (c *Client) RunShellCommand(ctx context.Context, id, sessionID, command string, termWidth int) (proto.ShellCommandResponse, error) {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/agent/sessions/%s/shell\", id, sessionID), nil, jsonBody(proto.ShellCommandRequest{\n\t\tCommand:   command,\n\t\tTermWidth: termWidth,\n\t}), http.Header{\"Content-Type\": []string{\"application/json\"}})\n\tif err != nil {\n\t\treturn proto.ShellCommandResponse{}, fmt.Errorf(\"failed to run shell command: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn proto.ShellCommandResponse{}, fmt.Errorf(\"failed to run shell command: status code %d\", rsp.StatusCode)\n\t}\n\tvar resp proto.ShellCommandResponse\n\tif err := json.NewDecoder(rsp.Body).Decode(&resp); err != nil {\n\t\treturn proto.ShellCommandResponse{}, fmt.Errorf(\"failed to decode shell command response: %w\", err)\n\t}\n\treturn resp, nil\n}\n\n// GetAgentSessionInfo retrieves the agent session info for a workspace.\nfunc (c *Client) GetAgentSessionInfo(ctx context.Context, id string, sessionID string) (*proto.AgentSession, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/agent/sessions/%s\", id, sessionID), nil, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get session agent info: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to get session agent info: status code %d\", rsp.StatusCode)\n\t}","sourceCodeStart":519,"sourceCodeEnd":555,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L519-L555","documentation":"RunShellCommand requires 200 OK. Any other status produces this error with the numeric status code; the response body is not decoded. Common statuses: 404 for unknown workspace/session, 401/403 for auth, 500 for server-side execution failure.","triggerScenarios":"Executing a shell command against a non-existent session (404), rejected auth (401/403), or a handler that failed before producing a result (5xx).","commonSituations":"Session ended/closed on the server while the client still holds its id; token expiry in long tool-running sessions; server error in the command executor.","solutions":["For 404, re-acquire a valid session ID (the old one may have been closed).","For 401/403, refresh credentials.","For 5xx, inspect server logs; retry with backoff if the command is idempotent.","Confirm the endpoint exists on the deployed server version."],"exampleFix":"// before\nif _, err := client.RunShellCommand(ctx, wsID, sid, cmd, w); err != nil {\n    return err\n}\n// after\nif _, err := client.RunShellCommand(ctx, wsID, sid, cmd, w); err != nil {\n    if strings.Contains(err.Error(), \"status code 404\") {\n        return fmt.Errorf(\"session %s closed; re-open session before running commands\", sid)\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"// Go: ensure the session exists before running commands\nif _, err := client.GetAgentSessionInfo(ctx, wsID, sid); err != nil {\n    return fmt.Errorf(\"cannot run command in session %s: %w\", sid, err)\n}","typeGuard":"// Go: extract and branch on status code\nfunc statusCode(err error) int {\n    var code int\n    fmt.Sscanf(err.Error(), \"failed to run shell command: status code %d\", &code)\n    return code\n}","tryCatchPattern":"_, err := client.RunShellCommand(ctx, wsID, sid, cmd, w)\nif err != nil && statusCode(err) >= 500 {\n    time.Sleep(2 * time.Second)\n    _, err = client.RunShellCommand(ctx, wsID, sid, cmd, w) // only retry idempotent commands\n}\nif err != nil { return err }","preventionTips":["Only retry on 5xx and only for idempotent commands.","Treat 404 as 'session closed' and re-open the session.","Refresh auth on 401/403 instead of retrying blindly.","Monitor server logs for executor failures matching client 500s."],"tags":["http-status","shell-execution"],"backgroundTag":"unexpected-http-status","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}