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

  1. Pass both ids: /security validate <scan-id> <finding-id>
  2. Or pass the full finding URI: /security validate security://scans/<scan-id>/findings/<finding-id>
  3. 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/
  4. 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

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


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