{"record":{"id":"1affc426886826ae","repo":"charmbracelet/crush","slug":"failed-to-answer-question-batch-w","errorCode":null,"errorMessage":"failed to answer question batch: %w","messagePattern":"failed to answer question batch: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":702,"sourceCode":"\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn false, fmt.Errorf(\"failed to grant permission: status code %d\", rsp.StatusCode)\n\t}\n\tvar resp proto.PermissionGrantResponse\n\tif err := json.NewDecoder(rsp.Body).Decode(&resp); err != nil {\n\t\treturn false, fmt.Errorf(\"failed to decode grant permission response: %w\", err)\n\t}\n\treturn resp.Resolved, nil\n}\n\n// AnswerQuestionBatch submits answers for a batch question on a\n// workspace. Returns true if this call resolved the pending\n// request, false if already resolved by another caller.\nfunc (c *Client) AnswerQuestionBatch(ctx context.Context, id string, req proto.QuestionAnswer) (bool, error) {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/questions/answer\", id), nil, jsonBody(req), http.Header{\"Content-Type\": []string{\"application/json\"}})\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"failed to answer question batch: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn false, fmt.Errorf(\"failed to answer question batch: status code %d\", rsp.StatusCode)\n\t}\n\tvar resp proto.QuestionAnswerResponse\n\tif err := json.NewDecoder(rsp.Body).Decode(&resp); err != nil {\n\t\treturn false, fmt.Errorf(\"failed to decode answer question batch response: %w\", err)\n\t}\n\treturn resp.Resolved, nil\n}\n\n// CancelQuestionBatch cancels the pending question batch on a\n// workspace. Returns true if a question was cancelled, false if\n// none was pending.\nfunc (c *Client) CancelQuestionBatch(ctx context.Context, id string) (bool, error) {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/questions/cancel\", id), nil, nil, http.Header{})\n\tif err != nil {","sourceCodeStart":684,"sourceCodeEnd":720,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L684-L720","documentation":"AnswerQuestionBatch POSTs answers to /workspaces/{id}/questions/answer. This error wraps any transport-level failure from c.post — connection refused, DNS failure, TLS error, or context cancellation — meaning the answers were never delivered. The pending question may still be unresolved.","triggerScenarios":"Calling AnswerQuestionBatch when the server is down or unreachable, the network drops mid-request, or the caller's context deadline expires before the POST finishes.","commonSituations":"Server restart between question receipt and answer; user answering on a flaky connection; long-running workspace where the context times out; wrong host/port configuration.","solutions":["Confirm server connectivity and retry AnswerQuestionBatch; the response's Resolved flag reports whether this call or another caller resolved the question.","Check the client base URL/port configuration.","Increase the context timeout if answers time out on large batches.","Handle a false Resolved return gracefully — another subscriber may have answered first, which is not an error."],"exampleFix":"// before\nresolved, err := client.AnswerQuestionBatch(ctx, wsID, answer)\nif err != nil { return err }\n// after\nresolved, err := client.AnswerQuestionBatch(ctx, wsID, answer)\nif err != nil {\n\t// safe to retry: answering is idempotent via Resolved flag\n\treturn fmt.Errorf(\"answering question batch on %s: %w\", wsID, err)\n}\nif !resolved { log.Info(\"question already resolved by another caller\") }","handlingStrategy":"retry","validationCode":"// Ensure the server is reachable and answers are well-formed before sending\nif serverReachable(ctx, baseURL) != nil {\n\treturn errors.New(\"cannot answer questions: server unreachable\")\n}","typeGuard":null,"tryCatchPattern":"resolved, err := client.AnswerQuestionBatch(ctx, wsID, answer)\nif err != nil {\n\tif errors.Is(err, context.DeadlineExceeded) { return err }\n\treturn retryAnswerBatch(ctx, wsID, answer, 3) // idempotent via Resolved flag\n}\nif !resolved { log.Info(\"question already resolved elsewhere\") }","preventionTips":["Retry answer submissions — the Resolved flag makes them idempotent","Keep contexts alive long enough for answer round-trips","Monitor server uptime to distinguish outage from bug","Handle false Resolved as success, not failure"],"tags":["http-client","network","questions"],"backgroundTag":"http-request-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}