charmbracelet/crush · error
failed to answer question batch: status code %d
Error message
failed to answer question batch: status code %d
What it means
AnswerQuestionBatch requires HTTP 200 from /workspaces/{id}/questions/answer. Any non-200 status produces this error with the code embedded. The server rejected the answer submission, so the question remains pending (or was rejected).
Source
Thrown at internal/client/proto.go:706
}
var resp proto.PermissionGrantResponse
if err := json.NewDecoder(rsp.Body).Decode(&resp); err != nil {
return false, fmt.Errorf("failed to decode grant permission response: %w", err)
}
return resp.Resolved, nil
}
// AnswerQuestionBatch submits answers for a batch question on a
// workspace. Returns true if this call resolved the pending
// request, false if already resolved by another caller.
func (c *Client) AnswerQuestionBatch(ctx context.Context, id string, req proto.QuestionAnswer) (bool, error) {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/questions/answer", id), nil, jsonBody(req), http.Header{"Content-Type": []string{"application/json"}})
if err != nil {
return false, fmt.Errorf("failed to answer question batch: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {
return false, fmt.Errorf("failed to answer question batch: status code %d", rsp.StatusCode)
}
var resp proto.QuestionAnswerResponse
if err := json.NewDecoder(rsp.Body).Decode(&resp); err != nil {
return false, fmt.Errorf("failed to decode answer question batch response: %w", err)
}
return resp.Resolved, nil
}
// CancelQuestionBatch cancels the pending question batch on a
// workspace. Returns true if a question was cancelled, false if
// none was pending.
func (c *Client) CancelQuestionBatch(ctx context.Context, id string) (bool, error) {
rsp, err := c.post(ctx, fmt.Sprintf("/workspaces/%s/questions/cancel", id), nil, nil, http.Header{})
if err != nil {
return false, fmt.Errorf("failed to cancel question batch: %w", err)
}
defer rsp.Body.Close()
if rsp.StatusCode != http.StatusOK {View on GitHub (pinned to 7944b8e522)
Solutions
- Read the status code in the error message and act: re-authenticate on 401/403, refresh the workspace id on 404, check server logs on 5xx.
- Validate the QuestionAnswer payload (IDs, format) against the current proto schema before sending.
- Re-authenticate if credentials expired.
- Retry after fixing the cause; check client/server version compatibility if 400 persists.
Defensive patterns
Strategy: try-catch
Validate before calling
// Sanity-check the answer payload before sending
if answer.ID == "" || len(answer.Answers) == 0 {
return errors.New("question answer requires an id and at least one answer")
} Try / catch
_, err := client.AnswerQuestionBatch(ctx, wsID, answer)
if err != nil && strings.Contains(err.Error(), "status code") {
if isAuthStatus(err) { // 401/403
return reauthenticateAndRetry(ctx, wsID, answer)
}
return fmt.Errorf("answering questions on %s: %w", wsID, err)
} Prevention
- Validate answer payloads against the current proto schema before sending
- Refresh expired credentials proactively
- Confirm the workspace id is live before answering
- Check server logs immediately when 5xx status codes appear
When it happens
Trigger: POSTing answers with an invalid/expired workspace id (404), insufficient auth (401/403), a QuestionAnswer payload the server rejects (400), or a server fault (5xx).
Common situations: Workspace id stale after reconnect; token expiry mid-session; client/server protocol mismatch; server 500 while persisting the answer.
Related errors
- failed to cancel question batch: status code %d
- failed to grant permission: status code %d
- failed to refresh OAuth token: status code %d
- failed to check project init: status code %d
- failed to mark project initialized: status code %d
AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29).
Data as JSON: /api/errors/8c29730389392564.
Report an issue: GitHub.