can1357/oh-my-pi · error · Error

Unknown security validation evidence: ${evidenceId}

Error message

Unknown security validation evidence: ${evidenceId}

What it means

updateValidation() merges supplied evidence with the finding's existing evidence into an evidenceById map, then requires every id in validation.evidenceIds to exist in that map. Referencing an evidence id that is neither already on the finding nor supplied in the evidence argument throws this error — validations cannot cite evidence the store has never seen.

Source

Thrown at packages/coding-agent/src/security/store.ts:405

		evidence: readonly SecurityEvidence[] = [],
	): Promise<SecurityFinding> {
		return withSecurityStoreWrite(this.#projectDirectory, async () => {
			const bundle = await this.#getBundleUnlocked(scanId);
			if (!bundle) throw new Error(`Unknown security scan: ${scanId}`);
			const index = bundle.findings.findIndex(finding => finding.id === findingId);
			if (index < 0) throw new Error(`Unknown security finding: ${findingId}`);
			const finding = bundle.findings[index];
			const evidenceById = new Map(finding.evidence.map(item => [item.id, item]));
			for (const item of evidence) evidenceById.set(item.id, item);
			const canonicalValidation: SecurityValidation = {
				status: validation.status,
				evidenceIds: [...new Set(validation.evidenceIds)],
			};
			if (validation.summary !== undefined) canonicalValidation.summary = validation.summary;
			if (validation.validatedAt !== undefined) canonicalValidation.validatedAt = validation.validatedAt;
			for (const evidenceId of canonicalValidation.evidenceIds) {
				if (!evidenceById.has(evidenceId)) {
					throw new Error(`Unknown security validation evidence: ${evidenceId}`);
				}
			}
			bundle.findings[index] = parseSecurityFinding({
				...finding,
				evidence: [...evidenceById.values()],
				validation: canonicalValidation,
			});
			if (bundle.sarif !== undefined) bundle.sarif = exportSecurityBundleToSarif(bundle);
			await this.#putBundleUnlocked(bundle);
			return bundle.findings[index];
		});
	}

	async compare(beforeScanId: string, afterScanId: string): Promise<SecurityComparisonReport> {
		const before = await this.getBundle(beforeScanId);
		const after = await this.getBundle(afterScanId);
		if (!before) throw new Error(`Unknown security scan: ${beforeScanId}`);
		if (!after) throw new Error(`Unknown security scan: ${afterScanId}`);

View on GitHub (pinned to 9690622007)

Solutions

  1. Pass the full SecurityEvidence objects for any new ids in the evidence parameter of updateValidation so their ids resolve.
  2. Only cite evidence ids already present on the finding: finding.evidence.map(e => e.id) — check before constructing validation.evidenceIds.
  3. Fix typos in evidenceIds; ids must exactly match an existing or supplied evidence item's id.
  4. Verify the evidence belongs to this finding; if not, update that finding instead.

Example fix

// before
await store.updateValidation(scanId, findingId, { status: 'confirmed', evidenceIds: ['ev-9'] }); // ev-9 never stored
// after
await store.updateValidation(scanId, findingId,
  { status: 'confirmed', evidenceIds: ['ev-9'] },
  [{ id: 'ev-9', /* ...full evidence... */ }]);
Defensive patterns

Strategy: validation

Validate before calling

const finding = await store.getFinding(scanId, findingId);
const known = new Set(finding?.evidence.map(e => e.id) ?? []);
for (const e of evidence) known.add(e.id);
const missing = validation.evidenceIds.filter(id => !known.has(id));
if (missing.length) throw new Error(`unsupplied evidence ids: ${missing.join(', ')}`);

Type guard

function allEvidenceKnown(validation: SecurityValidation, finding: SecurityFinding, extra: readonly SecurityEvidence[]): boolean {
  const ids = new Set([...finding.evidence.map(e => e.id), ...extra.map(e => e.id)]);
  return validation.evidenceIds.every(id => ids.has(id));
}

Try / catch

try {
  await store.updateValidation(scanId, findingId, validation, evidence);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Unknown security validation evidence')) {
    // attach the missing evidence objects in the `evidence` parameter and retry
  } else throw err;
}

Prevention

When it happens

Trigger: Calling updateValidation(scanId, findingId, { status, evidenceIds: [...], ... }, evidence) where an evidenceIds entry has no matching evidence.id — the id was invented, typo'd, belongs to another finding, or the corresponding evidence item was omitted from the evidence argument.

Common situations: Recording a validation that references evidence collected for a different finding; generating evidenceIds from a report without passing the evidence objects; evidence id renamed between runs; partial evidence upload where one item failed to persist.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/b6bfecbd3f148a9b. Report an issue: GitHub.