{"record":{"id":"8db9658a683fb06f","repo":"charmbracelet/crush","slug":"questions-must-be-an-array-w","errorCode":null,"errorMessage":"questions must be an array: %w","messagePattern":"questions must be an array: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/tools/question.go","lineNumber":51,"sourceCode":"\t\t*Alias\n\t}{\n\t\tAlias: (*Alias)(p),\n\t}\n\tif err := json.Unmarshal(data, aux); err != nil {\n\t\treturn err\n\t}\n\tif len(aux.Questions) == 0 {\n\t\treturn nil\n\t}\n\t// Try array first.\n\tif err := json.Unmarshal(aux.Questions, &p.Questions); err != nil {\n\t\t// Fall back to string-encoded JSON array.\n\t\tvar s string\n\t\tif err2 := json.Unmarshal(aux.Questions, &s); err2 != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err2 := json.Unmarshal([]byte(strings.TrimSpace(s)), &p.Questions); err2 != nil {\n\t\t\treturn fmt.Errorf(\"questions must be an array: %w\", err2)\n\t\t}\n\t}\n\treturn nil\n}\n\n// QuestionItem is a single question from the tool input.\ntype QuestionItem struct {\n\tLabel       string           `json:\"label,omitempty\" description:\"Short tab header label (3 words max).\"`\n\tType        string           `json:\"type\" description:\"The type of question: yes_no, single_choice, multi_choice, or free_text\"`\n\tQuestion    string           `json:\"question\" description:\"The question text\"`\n\tDescription string           `json:\"description\" description:\"Required markdown description shown below the question\"`\n\tChoices     []QuestionChoice `json:\"choices,omitempty\" description:\"List of choices\"`\n\tOptions     []QuestionChoice `json:\"options,omitempty\"` // alias for Choices\n}\n\n// GetChoices returns choices, preferring the Choices field over Options.\nfunc (q QuestionItem) GetChoices() []QuestionChoice {\n\tif len(q.Choices) > 0 {","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/tools/question.go#L33-L69","documentation":"The question tool accepts its questions field either as a real JSON array or as a string containing a JSON array. When the string-fallback path is taken, the trimmed string must itself parse into a question array; if json.Unmarshal into []QuestionItem fails, this error wraps the parse failure, meaning the input shape is neither a plain array nor a string-encoded array.","triggerScenarios":"Client sends questions as a string whose content is not a valid JSON array (e.g. plain prose, single-quoted pseudo-JSON, or a JSON object) — or the field is some other type that failed the primary array decode.","commonSituations":"Models emitting double-encoded or malformed JSON in tool arguments; middleware re-serializing arguments to strings; hand-written test payloads with unquoted JSON.","solutions":["Send questions as a proper JSON array of question objects, not a string","If double-encoded, decode the string once and confirm it is valid JSON array syntax","Log the raw aux.Questions value to see the exact malformed payload","Upgrade/fix the client or prompt that produces stringified arguments"],"exampleFix":"// before\n{\"questions\": \"[{question: 'title?'}]\"} // invalid inner JSON\n// after\n{\"questions\": [{\"question\": \"title?\", \"options\": [\"a\",\"b\"]}]}","handlingStrategy":"validation","validationCode":"switch v := raw.(type) {\ncase []any:\n    // ok: already an array\ncase string:\n    var check []any\n    if err := json.Unmarshal([]byte(strings.TrimSpace(v)), &check); err != nil {\n        return fmt.Errorf(\"questions is not a JSON array: %w\", err)\n    }\ndefault:\n    return fmt.Errorf(\"questions must be array or string-encoded array\")\n}","typeGuard":"func isQuestionArray(raw json.RawMessage) bool {\n    var arr []QuestionItem\n    return json.Unmarshal(raw, &arr) == nil\n}","tryCatchPattern":"if err := json.Unmarshal(data, &params); err != nil {\n    var syn *json.SyntaxError\n    if errors.As(err, &syn) {\n        // log syn.Offset to locate malformed inner JSON\n    }\n}","preventionTips":["Emit questions as a native JSON array in tool arguments","Avoid double-encoding arrays as strings","Log raw tool arguments when Unmarshal fails","Pin the client/model version that serializes arguments correctly"],"tags":["json","unmarshal","tool-input"],"backgroundTag":"schema-validation-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}