can1357/oh-my-pi · error
Security scan manifest contains duplicate finding references
Error message
Security scan manifest contains duplicate finding references
What it means
The bundle's scan manifest (scan.findingIds) must list each finding at most once. Duplicated manifest references indicate a corrupt or hand-edited manifest and would double-count findings in consumers, so parseSecurityScanBundle rejects the bundle.
Source
Thrown at packages/coding-agent/src/security/contracts/validation.ts:39
}
export function parseSecurityScanPlan(value: unknown): SecurityScanPlan {
const { securityScanPlanSchema } = getSecurityContractSchemas();
const result = securityScanPlanSchema(value);
if (result instanceof type.errors) throw schemaError("Security scan plan", result);
return result as SecurityScanPlan;
}
export function parseSecurityScanBundle(value: unknown): SecurityScanBundle {
const { securityScanBundleSchema } = getSecurityContractSchemas();
const result = securityScanBundleSchema(value);
if (result instanceof type.errors) throw schemaError("Security scan bundle", result);
const bundle = result as SecurityScanBundle;
const findingIds = new Set(bundle.findings.map(finding => finding.id));
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) {View on GitHub (pinned to 9690622007)
Solutions
- Regenerate the bundle so scan.findingIds is derived as the unique set of finding ids
- Deduplicate the manifest before parse: findingIds: [...new Set(raw.scan.findingIds)]
- Validate pre-parse: compare new Set(manifest).size against manifest.length
- Fix the exporting tool to build the manifest from the findings array
Example fix
// before parseSecurityScanBundle(raw); // raw.scan.findingIds has a duplicate // after raw.scan.findingIds = [...new Set(raw.scan.findingIds)]; parseSecurityScanBundle(raw);
Defensive patterns
Strategy: validation
Validate before calling
const m = raw.scan.findingIds;
if (new Set(m).size !== m.length) throw new Error("Manifest has duplicate finding references"); Try / catch
try {
bundle = parseSecurityScanBundle(value);
} catch (err) {
if (err instanceof Error && err.message === "Security scan manifest contains duplicate finding references") {
raw.scan.findingIds = [...new Set(raw.scan.findingIds)];
bundle = parseSecurityScanBundle(raw);
} else throw err;
} Prevention
- Build scan.findingIds as a set-derived unique list at generation time
- Never append to an existing manifest when merging bundles
- Round-trip bundles through parseSecurityScanBundle in CI to catch corrupt manifests early
When it happens
Trigger: Parsing a bundle JSON where bundle.scan.findingIds contains the same id twice (findings array itself may be fine).
Common situations: Scripted bundle generation appending to findingIds instead of replacing it; manual edits to exported JSON; a merge tool that deduplicated findings but not the manifest.
Related errors
- lookbackDays must be a positive integer or 'all'
- Security scan contains duplicate finding ids
- Security scan references missing finding: ${findingId}
- Security scan omits finding from manifest: ${findingId}
- Finding ${finding.id} belongs to ${finding.scanId}, expected
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/fa68ca785001fef9.
Report an issue: GitHub.