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
- Pass the full SecurityEvidence objects for any new ids in the evidence parameter of updateValidation so their ids resolve.
- Only cite evidence ids already present on the finding: finding.evidence.map(e => e.id) — check before constructing validation.evidenceIds.
- Fix typos in evidenceIds; ids must exactly match an existing or supplied evidence item's id.
- 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
- Always pass full evidence objects for any evidenceIds not already on the finding.
- Build evidenceIds from finding.evidence plus the evidence you supply — never from memory.
- Enforce evidence id uniqueness and exact-match when generating validations.
- Keep evidence collection and validation submission in one atomic step.
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
- Unknown security scan: ${scanId}
- Unknown security finding: ${findingId}
- Unknown security scan: ${beforeScanId}
- Plugin ${name} not found in runtime config
- Marketplace "${name}" not found
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/b6bfecbd3f148a9b.
Report an issue: GitHub.