can1357/oh-my-pi · error · ToolError
Invalid report format. ${reportIssueDeviceUsage()}
Error message
Invalid report format. ${reportIssueDeviceUsage()} What it means
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.
Source
Thrown at packages/coding-agent/src/tools/report-tool-issue.ts:95
function parseReportIssueBody(text: string): { tool: string; report: string } {
const body = text.trim();
if (!body) {
throw new ToolError(`Empty report. ${reportIssueDeviceUsage()}`);
}
const firstNewline = body.indexOf("\n");
if (firstNewline >= 0) {
const tool = body.slice(0, firstNewline).trim();
const report = body.slice(firstNewline + 1).trim();
if (tool && report) return { tool, report };
}
const colon = body.indexOf(":");
if (colon > 0) {
const tool = body.slice(0, colon).trim();
const report = body.slice(colon + 1).trim();
if (tool && report) return { tool, report };
}
throw new ToolError(`Invalid report format. ${reportIssueDeviceUsage()}`);
}
/**
* Whether Auto-QA is active for this session.
*
* Precedence: `PI_AUTO_QA` env flag > explicit `dev.autoqa` setting >
* default-on unless the user previously denied consent. The denial veto only
* applies to the default: explicitly configuring `dev.autoqa: true` re-enables
* injection (recording still no-ops until consent is granted).
*/
export function isAutoQaEnabled(settings?: Settings): boolean {
let fallback = false;
if (settings) {
const enabled = !!settings.get("dev.autoqa");
fallback = settings.isConfigured("dev.autoqa")
? enabled
: enabled && settings.get("dev.autoqaConsent") !== "denied";
}View on GitHub (pinned to 9690622007)
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
Example fix
// before
callReportIssue("bash failed");
// after
callReportIssue("bash\nThe command 'bun test' failed with exit code 1."); Defensive patterns
Strategy: validation
Validate before calling
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>'"); Try / catch
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; } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- objective is required when op=create
- token_budget must be a positive integer when provided
- `pat` must be a non-empty pattern
- skip must be a non-negative number
- Empty report. ${reportIssueDeviceUsage()}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/14eb0452d2d8b25d.
Report an issue: GitHub.