{"record":{"id":"81530c0a4f6572a9","repo":"charmbracelet/crush","slug":"failed-to-decode-agent-status-w","errorCode":null,"errorMessage":"failed to decode agent status: %w","messagePattern":"failed to decode agent status: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":468,"sourceCode":"\tif rsp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to clear session agent queued prompts: status code %d\", rsp.StatusCode)\n\t}\n\treturn nil\n}\n\n// GetAgentInfo retrieves the agent status for a workspace.\nfunc (c *Client) GetAgentInfo(ctx context.Context, id string) (*proto.AgentInfo, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/agent\", id), nil, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get agent status: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif err := checkStatus(rsp); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get agent status: %w\", err)\n\t}\n\tvar info proto.AgentInfo\n\tif err := json.NewDecoder(rsp.Body).Decode(&info); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode agent status: %w\", err)\n\t}\n\treturn &info, nil\n}\n\n// UpdateAgent triggers an agent model update on the server.\nfunc (c *Client) UpdateAgent(ctx context.Context, id string) error {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/agent/update\", id), nil, nil, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to update agent: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to update agent: status code %d\", rsp.StatusCode)\n\t}\n\treturn nil\n}\n\n// SendMessage sends a message to the agent for a workspace.","sourceCodeStart":450,"sourceCodeEnd":486,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L450-L486","documentation":"After a successful checkStatus, GetAgentInfo decodes the body into proto.AgentInfo. If the body is not valid JSON matching proto.AgentInfo (empty body, HTML from a proxy, schema drift), the decode fails and this error wraps the json error.","triggerScenarios":"Server returns 200 with a body that fails to unmarshal into proto.AgentInfo — version mismatch where fields changed types, empty response, or proxy-injected content.","commonSituations":"Client and server built from different versions after a proto.AgentInfo schema change; misbehaving reverse proxy; server returning null or a wrapped object instead of the expected struct.","solutions":["Align client and server versions so proto.AgentInfo matches","Log the raw response body on decode failure","Check for proxies altering the response","Update the generated proto types if the server schema changed"],"exampleFix":"// before\nvar info proto.AgentInfo\nif err := json.NewDecoder(rsp.Body).Decode(&info); err != nil {\n\treturn nil, fmt.Errorf(\"failed to decode agent status: %w\", err)\n}\n// after\nbody, _ := io.ReadAll(rsp.Body)\nvar info proto.AgentInfo\nif err := json.Unmarshal(body, &info); err != nil {\n\treturn nil, fmt.Errorf(\"decode agent status %q: %w\", body, err)\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"func decodeAgentInfo(r io.Reader) (*proto.AgentInfo, error) {\n\tbody, err := io.ReadAll(r)\n\tif err != nil { return nil, err }\n\tif len(bytes.TrimSpace(body)) == 0 { return nil, errors.New(\"empty agent status body\") }\n\tvar info proto.AgentInfo\n\tif err := json.Unmarshal(body, &info); err != nil {\n\t\treturn nil, fmt.Errorf(\"agent status body %q: %w\", body, err)\n\t}\n\treturn &info, nil\n}","tryCatchPattern":"info, err := client.GetAgentInfo(ctx, wsID)\nif err != nil && strings.Contains(err.Error(), \"failed to decode agent status\") {\n\t// do not retry: schema mismatch — log body and check versions\n}","preventionTips":["Keep proto.AgentInfo definitions identical on client and server","Capture the raw body on decode failure","Block proxies/HTML error pages from API routes","Add golden tests for the agent status response shape"],"tags":["json","decode","schema-mismatch"],"backgroundTag":"json-decode-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}