can1357/oh-my-pi · info
validate requires a finding URI or <scan-id> <finding-id>
Error message
validate requires a finding URI or <scan-id> <finding-id>
What it means
The /security validate subcommand requires a way to identify a specific finding to validate: either a full security:// URI of the form security://scans/<scan-id>/findings/<finding-id>, or two positional arguments <scan-id> <finding-id>. findingTarget() throws this error when the trimmed input matches neither form — the URI regex fails and parseCommandArgs() yields fewer than two tokens. It is a usage-guard so the command never proceeds with a malformed or missing finding reference.
Source
Thrown at packages/coding-agent/src/slash-commands/helpers/security.ts:148
archiveExisting: options.archiveExisting,
credentialId: options.credentialId,
model: runtime.session.model,
};
return coordinatorFor(runtime).preflight(input);
}
function scanIdFromInput(value: string): string {
const trimmed = value.trim();
const match = trimmed.match(/^security:\/\/scans\/([^/]+)/);
return match?.[1] ?? trimmed;
}
function findingTarget(value: string): { uri: string; scanId: string; findingId: string } {
const trimmed = value.trim();
const uriMatch = trimmed.match(/^security:\/\/scans\/([^/]+)\/findings\/([^/]+)$/);
if (uriMatch) return { uri: trimmed, scanId: uriMatch[1]!, findingId: uriMatch[2]! };
const [scanId, findingId] = parseCommandArgs(trimmed);
if (!scanId || !findingId) throw new Error("validate requires a finding URI or <scan-id> <finding-id>");
return { uri: `security://scans/${scanId}/findings/${findingId}`, scanId, findingId };
}
async function showResource(runtime: SlashCommandRuntime, rest: string): Promise<void> {
const raw = rest.trim();
if (!raw) throw new Error("show requires a scan id or security:// URI");
const uri = raw.startsWith("security://") ? raw : `security://scans/${scanIdFromInput(raw)}`;
const handler = new SecurityProtocolHandler(undefined, () => true);
const resource = await handler.resolve(parseInternalUrl(uri), { cwd: runtime.cwd });
await runtime.output(resource.content);
}
async function importResults(runtime: SlashCommandRuntime, rest: string): Promise<void> {
const [source] = parseCommandArgs(rest);
if (!source) throw new Error("import requires a SARIF file or Codex Security bundle directory");
const store = await SecurityStore.openForCwd(runtime.cwd);
const absolute = path.resolve(runtime.cwd, source);
const stats = await fs.stat(absolute);View on GitHub (pinned to 9690622007)
Solutions
- Pass both ids: /security validate <scan-id> <finding-id>
- Or pass the full finding URI: /security validate security://scans/<scan-id>/findings/<finding-id>
- Copy the URI exactly as shown by /security show or the findings list output — the regex requires exactly two non-slash segments after /scans/ and /findings/
- Quote arguments containing spaces so parseCommandArgs sees two separate tokens
Example fix
// before /security validate scan-abc // after /security validate scan-abc finding-42 // or /security validate security://scans/scan-abc/findings/finding-42
Defensive patterns
Strategy: validation
Validate before calling
const SECURITY_FINDING_URI = /^security:\/\/scans\/([^/]+)\/findings\/([^/]+)$/;
function validateFindingTarget(value: string): boolean {
const trimmed = value.trim();
if (SECURITY_FINDING_URI.test(trimmed)) return true;
const tokens = trimmed.split(/\s+/).filter(Boolean);
return tokens.length === 2;
}
// call before issuing: if (!validateFindingTarget(input)) prompt for missing ids Type guard
function isFindingUri(value: string): value is `security://scans/${string}/findings/${string}` {
return /^security:\/\/scans\/[^/]+\/findings\/[^/]+$/.test(value.trim());
} Try / catch
try {
await runSlashCommand(`/security validate ${input}`);
} catch (err) {
if (err instanceof Error && err.message.startsWith("validate requires")) {
// surface usage: need security:// URI or <scan-id> <finding-id>
} else throw err;
} Prevention
- Always paste the full finding URI shown by /security show or findings output
- When scripting, assert both scan-id and finding-id variables are non-empty before invoking
- Remember the URI regex allows no slashes inside the two id segments
- Quote whitespace-containing inputs so argument parsing yields exactly two tokens
When it happens
Trigger: Running /security validate with no arguments; with only one token (e.g. /security validate scan-123); or with a malformed URI (e.g. missing the findings segment, wrong scheme, or trailing path parts) such that the regex ^security:\/\/scans\/([^/]+)\/findings\/([^/]+)$ does not match and parseCommandArgs returns fewer than 2 args.
Common situations: Developer copies a scan id but forgets the finding id; pastes a truncated URI from a renderer that stripped it; uses a different URI scheme (https://) or an old URI shape; whitespace-only argument after command parsing stripped it.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- show requires a scan id or security:// URI
- import requires a SARIF file or Codex Security bundle direct
- export requires <scan-id> --output <path> [--format bundle|s
- Unknown export format: ${value}
- Unknown export option: ${token}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/2fcb517729b2e926.
Report an issue: GitHub.