{"record":{"id":"e37f783438f08d6e","repo":"can1357/oh-my-pi","slug":"occurrence-occurrence-id-references-missing-evi","errorCode":null,"errorMessage":"Occurrence ${occurrence.id} references missing evidence: ${evidenceId}","messagePattern":"Occurrence (.+?) references missing evidence: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/security/contracts/validation.ts","lineNumber":63,"sourceCode":"\t\tif (!referencedFindingIds.has(findingId))\n\t\t\tthrow new Error(`Security scan omits finding from manifest: ${findingId}`);\n\t}\n\tfor (const finding of bundle.findings) {\n\t\tif (finding.scanId !== bundle.scan.id) {\n\t\t\tthrow new Error(`Finding ${finding.id} belongs to ${finding.scanId}, expected ${bundle.scan.id}`);\n\t\t}\n\t\tconst evidenceIds = new Set(finding.evidence.map(evidence => evidence.id));\n\t\tif (evidenceIds.size !== finding.evidence.length) {\n\t\t\tthrow new Error(`Finding ${finding.id} contains duplicate evidence ids`);\n\t\t}\n\t\tconst occurrenceIds = new Set(finding.occurrences.map(occurrence => occurrence.id));\n\t\tif (occurrenceIds.size !== finding.occurrences.length) {\n\t\t\tthrow new Error(`Finding ${finding.id} contains duplicate occurrence ids`);\n\t\t}\n\t\tfor (const occurrence of finding.occurrences) {\n\t\t\tfor (const evidenceId of occurrence.evidenceIds) {\n\t\t\t\tif (!evidenceIds.has(evidenceId)) {\n\t\t\t\t\tthrow new Error(`Occurrence ${occurrence.id} references missing evidence: ${evidenceId}`);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn bundle;\n}\n","sourceCodeStart":45,"sourceCodeEnd":70,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/security/contracts/validation.ts#L45-L70","documentation":"parseSecurityScanBundle verifies that every evidenceId referenced by an occurrence exists in the finding's evidence array. A missing reference means an occurrence cites evidence that was never recorded (or was removed), so the bundle fails referential-integrity checks before consumers try to resolve it.","triggerScenarios":"Loading/importing a bundle where occurrence.evidenceIds contains an id absent from finding.evidence — e.g. evidence entries dropped by an importer filter while occurrences were copied verbatim, or a typo'd/hard-deleted evidence id in a hand-edited bundle.","commonSituations":"SARIF import where result-to-evidence mapping references locations outside the emitted evidence set; pruning evidence to shrink files without updating occurrences.","solutions":["Add the missing evidence entry with the referenced id, or remove the stale id from occurrence.evidenceIds.","Re-derive evidenceIds from actual evidence ids programmatically rather than maintaining them by hand.","If importing, fix the importer to only reference evidence it actually emits, and emit evidence for every cited location.","Re-run the scan to produce a self-consistent bundle."],"exampleFix":"// before\noccurrence.evidenceIds = [...occurrence.evidenceIds, missingId];\n// after\nconst valid = new Set(finding.evidence.map(e => e.id));\noccurrence.evidenceIds = occurrence.evidenceIds.filter(id => valid.has(id));","handlingStrategy":"validation","validationCode":"for (const f of bundle.findings) {\n  const evidenceIds = new Set(f.evidence.map(e => e.id));\n  for (const o of f.occurrences) {\n    const missing = o.evidenceIds.filter(id => !evidenceIds.has(id));\n    if (missing.length) throw new Error(`occurrence ${o.id} missing evidence: ${missing.join(\", \")}`);\n  }\n}","typeGuard":"function evidenceReferencesResolve(finding: SecurityFinding): boolean {\n  const ids = new Set(finding.evidence.map(e => e.id));\n  return finding.occurrences.every(o => o.evidenceIds.every(id => ids.has(id)));\n}","tryCatchPattern":"try {\n  const bundle = importSarif(path);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"references missing evidence\")) {\n    // re-import with evidence generation enabled or repair the mapping\n  } else throw err;\n}","preventionTips":["Derive occurrence.evidenceIds from the evidence array at build time, never in parallel by hand.","If pruning evidence, cascade the prune to occurrences' evidenceIds in the same pass.","Round-trip validate (parse) every bundle produced by an importer before storing it."],"tags":["validation","referential-integrity","security-scan"],"backgroundTag":"missing-referenced-entity","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}