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

  1. Format the body as '<tool-name>\n<report text>' with both parts non-empty
  2. Alternatively use '<tool-name>: <report text>' on a single line
  3. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/14eb0452d2d8b25d. Report an issue: GitHub.