can1357/oh-my-pi · error

Finding ${finding.id} contains duplicate evidence ids

Error message

Finding ${finding.id} contains duplicate evidence ids

What it means

parseSecurityScanBundle checks that every finding's evidence entries have unique ids by comparing Set size to array length. Duplicate evidence ids within one finding indicate malformed evidence collection — deduplication must happen at production time because consumers key on evidence.id.

Source

Thrown at packages/coding-agent/src/security/contracts/validation.ts:54

	if (findingIds.size !== bundle.findings.length) throw new Error("Security scan contains duplicate finding ids");
	const referencedFindingIds = new Set(bundle.scan.findingIds);
	if (referencedFindingIds.size !== bundle.scan.findingIds.length) {
		throw new Error("Security scan manifest contains duplicate finding references");
	}
	for (const findingId of referencedFindingIds) {
		if (!findingIds.has(findingId)) throw new Error(`Security scan references missing finding: ${findingId}`);
	}
	for (const findingId of findingIds) {
		if (!referencedFindingIds.has(findingId))
			throw new Error(`Security scan omits finding from manifest: ${findingId}`);
	}
	for (const finding of bundle.findings) {
		if (finding.scanId !== bundle.scan.id) {
			throw new Error(`Finding ${finding.id} belongs to ${finding.scanId}, expected ${bundle.scan.id}`);
		}
		const evidenceIds = new Set(finding.evidence.map(evidence => evidence.id));
		if (evidenceIds.size !== finding.evidence.length) {
			throw new Error(`Finding ${finding.id} contains duplicate evidence ids`);
		}
		const occurrenceIds = new Set(finding.occurrences.map(occurrence => occurrence.id));
		if (occurrenceIds.size !== finding.occurrences.length) {
			throw new Error(`Finding ${finding.id} contains duplicate occurrence ids`);
		}
		for (const occurrence of finding.occurrences) {
			for (const evidenceId of occurrence.evidenceIds) {
				if (!evidenceIds.has(evidenceId)) {
					throw new Error(`Occurrence ${occurrence.id} references missing evidence: ${evidenceId}`);
				}
			}
		}
	}
	return bundle;
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Deduplicate the evidence array by id in the bundle JSON before loading.
  2. Fix the importer/generator so evidence ids are unique (e.g. derive from result index or a stable hash of the evidence content).
  3. Re-run the scan to regenerate a clean bundle if the source store is corrupted.

Example fix

// before
finding.evidence = [...oldEvidence, ...newEvidence]; // overlapping entries
// after
const merged = new Map(finding.evidence.map(e => [e.id, e]));
finding.evidence = [...merged.values()];
Defensive patterns

Strategy: validation

Validate before calling

for (const f of bundle.findings) {
  const ids = f.evidence.map(e => e.id);
  if (new Set(ids).size !== ids.length) throw new Error(`duplicate evidence ids in finding ${f.id}`);
}

Type guard

function hasUniqueEvidenceIds(finding: SecurityFinding): boolean {
  const ids = finding.evidence.map(e => e.id);
  return new Set(ids).size === ids.length;
}

Try / catch

try {
  const bundle = readBundle(scanId);
} catch (err) {
  if (err instanceof Error && err.message.includes("duplicate evidence ids")) {
    // regenerate or deduplicate the bundle before retrying
  } else throw err;
}

Prevention

When it happens

Trigger: Calling bundle()/readBundle()/importSarif()/importCodexSecurityBundle() on a bundle where a finding's evidence array contains two entries with the same id — typically from an importer appending the same evidence twice or a generator bug.

Common situations: SARIF imports where a result maps to the same code location multiple times and the import code assigns the same evidence id each time; retries during scan generation that re-append evidence without clearing the array.

Related errors


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