can1357/oh-my-pi · info

Unknown export option: ${token}

Error message

Unknown export option: ${token}

What it means

/export accepts only the flags --output and --format. Any other positional or flag token encountered after the scan id makes exportResults() throw 'Unknown export option: <token>'. The loop validates every token from index 1 onward and fails fast on the first unrecognized one, before any store access.

Source

Thrown at packages/coding-agent/src/slash-commands/helpers/security.ts:189

	await runtime.output(`Imported ${bundle.findings.length} finding(s) as security scan ${bundle.scan.id}.`);
}

async function exportResults(runtime: SlashCommandRuntime, rest: string): Promise<void> {
	const tokens = parseCommandArgs(rest);
	const scanId = tokens[0];
	if (!scanId) throw new Error("export requires <scan-id> --output <path> [--format bundle|sarif|report]");
	let outputPath: string | undefined;
	let format: "bundle" | "sarif" | "report" = "bundle";
	for (let index = 1; index < tokens.length; index++) {
		const token = tokens[index]!;
		if (token === "--output") outputPath = requireToken(tokens, ++index, token);
		else if (token === "--format") {
			const value = requireToken(tokens, ++index, token);
			if (value !== "bundle" && value !== "sarif" && value !== "report") {
				throw new Error(`Unknown export format: ${value}`);
			}
			format = value;
		} else throw new Error(`Unknown export option: ${token}`);
	}
	if (!outputPath) throw new Error("export requires --output <path>");
	const store = await SecurityStore.openForCwd(runtime.cwd);
	const bundle = await store.getBundle(scanIdFromInput(scanId));
	if (!bundle) throw new Error(`Unknown security scan: ${scanId}`);
	let content: string;
	if (format === "sarif") {
		if (!bundle.sarif) throw new Error(`Security scan ${scanId} has no SARIF result`);
		content = `${JSON.stringify(bundle.sarif, null, 2)}\n`;
	} else if (format === "report") {
		if (bundle.report === undefined) throw new Error(`Security scan ${scanId} has no report`);
		content = bundle.report;
	} else {
		content = `${JSON.stringify(bundle, null, 2)}\n`;
	}
	const absolute = path.resolve(runtime.cwd, outputPath);
	await writeSecurityFileAtomic(absolute, content, { hardenParent: false });
	await runtime.output(`Exported security scan ${scanId} to ${shortenPath(absolute)}.`);

View on GitHub (pinned to 9690622007)

Solutions

  1. Use exactly --output <path> for the destination file
  2. Use exactly --format bundle|sarif|report for the format
  3. Remove any extra/unknown tokens after the scan id

Example fix

// before
/security export scan-abc -o out.json
// after
/security export scan-abc --output out.json
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED_EXPORT_FLAGS = new Set(["--output", "--format"]);
function validateExportTokens(rest: string): string[] {
  return rest.trim().split(/\s+/).filter(t => t.startsWith("--"))
    .filter(t => !ALLOWED_EXPORT_FLAGS.has(t));
}
// if validateExportTokens(rest).length > 0, fix flags before invoking

Try / catch

try {
  await runSlashCommand(`/security export ${rest}`);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("Unknown export option:")) {
    // strip or correct the offending token reported in err.message
  } else throw err;
}

Prevention

When it happens

Trigger: Running /security export <scan-id> --file out.json (wrong flag name); passing extra positional arguments (e.g. a second id); using --out or -o shorthand; passing --output without a value is handled by requireToken but a stray value like --verbose triggers this error.

Common situations: Muscle-memory from other CLIs (-o, --out); pasting an export command with extra trailing tokens from notes; confusing /security export syntax with a different tool's export flags.

Related errors


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