{"record":{"id":"14eb0452d2d8b25d","repo":"can1357/oh-my-pi","slug":"invalid-report-format-reportissuedeviceusage","errorCode":null,"errorMessage":"Invalid report format. ${reportIssueDeviceUsage()}","messagePattern":"Invalid report format\\. (.+?)","errorType":"validation","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/report-tool-issue.ts","lineNumber":95,"sourceCode":"\nfunction parseReportIssueBody(text: string): { tool: string; report: string } {\n\tconst body = text.trim();\n\tif (!body) {\n\t\tthrow new ToolError(`Empty report. ${reportIssueDeviceUsage()}`);\n\t}\n\tconst firstNewline = body.indexOf(\"\\n\");\n\tif (firstNewline >= 0) {\n\t\tconst tool = body.slice(0, firstNewline).trim();\n\t\tconst report = body.slice(firstNewline + 1).trim();\n\t\tif (tool && report) return { tool, report };\n\t}\n\tconst colon = body.indexOf(\":\");\n\tif (colon > 0) {\n\t\tconst tool = body.slice(0, colon).trim();\n\t\tconst report = body.slice(colon + 1).trim();\n\t\tif (tool && report) return { tool, report };\n\t}\n\tthrow new ToolError(`Invalid report format. ${reportIssueDeviceUsage()}`);\n}\n\n/**\n * Whether Auto-QA is active for this session.\n *\n * Precedence: `PI_AUTO_QA` env flag > explicit `dev.autoqa` setting >\n * default-on unless the user previously denied consent. The denial veto only\n * applies to the default: explicitly configuring `dev.autoqa: true` re-enables\n * injection (recording still no-ops until consent is granted).\n */\nexport function isAutoQaEnabled(settings?: Settings): boolean {\n\tlet fallback = false;\n\tif (settings) {\n\t\tconst enabled = !!settings.get(\"dev.autoqa\");\n\t\tfallback = settings.isConfigured(\"dev.autoqa\")\n\t\t\t? enabled\n\t\t\t: enabled && settings.get(\"dev.autoqaConsent\") !== \"denied\";\n\t}","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/report-tool-issue.ts#L77-L113","documentation":"After the empty check, parseReportIssueBody tries two shapes: newline-separated (first line = tool, rest = report) or colon-separated (before colon = tool, after = report). If neither yields both a non-empty tool and a non-empty report, it throws this ToolError with usage instructions.","triggerScenarios":"Body like \"just some text\" (no newline and no colon), \"tool:\" (empty report after colon), \": report\" (empty tool before colon), or a single-line body that only names the tool.","commonSituations":"The model sends a one-line message without the tool/report split; a prompt template collapses the newline; report text containing only whitespace after the separator.","solutions":["Format the body as '<tool-name>\\n<report text>' with both parts non-empty","Alternatively use '<tool-name>: <report text>' on a single line","Ensure the report text itself is not empty after trimming"],"exampleFix":"// before\ncallReportIssue(\"bash failed\");\n// after\ncallReportIssue(\"bash\\nThe command 'bun test' failed with exit code 1.\");","handlingStrategy":"validation","validationCode":"const t = body.trim(); const sep = t.includes(\"\\n\") ? t.indexOf(\"\\n\") : t.includes(\":\") ? t.indexOf(\":\") : -1; if (sep < 1) throw new Error(\"Body must be '<tool>\\\\n<report>' or '<tool>: <report>'\");","typeGuard":null,"tryCatchPattern":"try { await reportIssue(body); } catch (e) { if (e instanceof ToolError && e.message.includes(\"Invalid report format\")) { body = `${toolName}\\n${reportText}`; /* retry once with canonical format */ } else throw e; }","preventionTips":["Put the tool name alone on the first line, report on subsequent lines","Never send a single-line body containing only the tool name","Trim both parts and confirm both are non-empty before sending"],"tags":["tool-input","validation","format"],"backgroundTag":"tool-argument-format-invalid","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}