{"record":{"id":"97f27295ad199213","repo":"mvanhorn/last30days-skill","slug":"emit-must-be-compact-or-html-got-q","errorCode":null,"errorMessage":"emit must be 'compact' or 'html', got %q","messagePattern":"emit must be 'compact' or 'html', got %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mcp/internal/tools/research.go","lineNumber":132,"sourceCode":"\treturn value, nil\n}\n\nfunc emitArgument(args map[string]any) (string, error) {\n\traw, ok := args[\"emit\"]\n\tif !ok {\n\t\treturn \"compact\", nil\n\t}\n\tvalue, ok := raw.(string)\n\tif !ok {\n\t\treturn \"\", errors.New(\"emit must be a string\")\n\t}\n\tswitch value {\n\tcase \"\":\n\t\treturn \"compact\", nil\n\tcase \"compact\", \"html\":\n\t\treturn value, nil\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"emit must be 'compact' or 'html', got %q\", value)\n\t}\n}\n\nfunc boolArgument(args map[string]any, name string) (bool, error) {\n\traw, ok := args[name]\n\tif !ok {\n\t\treturn false, nil\n\t}\n\tvalue, ok := raw.(bool)\n\tif !ok {\n\t\treturn false, fmt.Errorf(\"%s must be a boolean\", name)\n\t}\n\treturn value, nil\n}\n\n// formatRunError flattens engine.Run's distinct error shapes into a single\n// user-facing message that includes the relevant stderr context.\nfunc formatRunError(runErr error, res *engine.RunResult) string {","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/mvanhorn/last30days-skill/blob/c7460f6114449ddfe6ea3fc2f23c3d910c0e740c/mcp/internal/tools/research.go#L114-L150","documentation":"Thrown by emitArgument (mcp/internal/tools/research.go:132) when the 'research' tool's optional 'emit' argument is a string outside the allowed set. The switch accepts \"\" (treated as \"compact\"), \"compact\", and \"html\"; any other value — \"md\", \"text\", \"json\", \"HTML\" — hits the default case and the offending value is echoed with %q. This is the research tool's counterpart to preflight's format enum; the two vocabularies differ on purpose (research emits compact/html artifacts, preflight emits text/json summaries), which is a common mix-up.","triggerScenarios":"Calling 'research' with {\"emit\": \"json\"}, {\"emit\": \"text\"}, {\"emit\": \"markdown\"}, or {\"emit\": \"HTML\"}. Most often a model or script reuses the preflight tool's format values ('text'/'json') on research, guesses 'markdown' for a report, or gets the case wrong.","commonSituations":"Cross-tool vocabulary confusion between preflight's format ('text'/'json') and research's emit ('compact'/'html'); model-invented enum values; uppercase variants; legacy docs or examples referencing an emit mode that was removed/renamed.","solutions":["Use emit: \"compact\" (default, inline synthesis) or emit: \"html\" (also saves a shareable HTML brief) — or omit emit entirely.","Don't pass 'json' or 'text' to research; those belong to the preflight tool's format argument.","Check casing — the comparison is case-sensitive and exact.","Client authors: derive allowed values from the tool's inputSchema description rather than hardcoding."],"exampleFix":"// before\n{\"name\": \"research\", \"arguments\": {\"topic\": \"rust 2026\", \"emit\": \"markdown\"}}\n// -> error: emit must be 'compact' or 'html', got \"markdown\"\n\n// after\n{\"name\": \"research\", \"arguments\": {\"topic\": \"rust 2026\", \"emit\": \"html\"}}","handlingStrategy":"validation","validationCode":"// Validate emit before calling research.\nfunc validEmit(v any) bool {\n\tswitch v {\n\tcase nil, \"\", \"compact\", \"html\":\n\t\treturn true\n\t}\n\treturn false\n}\n\nif !validEmit(args[\"emit\"]) {\n    args[\"emit\"] = \"compact\" // or reject, per your policy\n}","typeGuard":"func isResearchEmit(v any) bool {\n\tswitch v {\n\tcase nil, \"\", \"compact\", \"html\":\n\t\treturn true\n\t}\n\treturn false\n}","tryCatchPattern":null,"preventionTips":["Remember the split: research takes emit=compact|html; preflight takes format=text|json. 'json' and 'text' are invalid for research.","Defaulting to omitting emit is safest — the server treats missing as compact.","Keep enums lowercase and exact; no case-insensitive matching is done."],"tags":["go","mcp","validation","enum","arguments"],"backgroundTag":null,"analyzedSha":"c7460f6114449ddfe6ea3fc2f23c3d910c0e740c","analyzedAt":"2026-08-15T03:34:49.540Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}