can1357/oh-my-pi · error
Finding ${finding.id} belongs to ${finding.scanId}, expected
Error message
Finding ${finding.id} belongs to ${finding.scanId}, expected ${bundle.scan.id} What it means
parseSecurityScanBundle validates referential integrity of a security scan bundle after schema validation. Every finding in bundle.findings must declare the same scanId as the bundle's scan record; a mismatch means the findings array and the scan manifest describe different scans. The library throws to prevent mixing findings across scans when loading, importing (Sarif/Codex), or reading bundles from disk.
Source
Thrown at packages/coding-agent/src/security/contracts/validation.ts:50
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) {
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
- Open the bundle JSON and compare each finding's scanId with scan.id; make them consistent (usually the finding's scanId is stale — update it to match bundle.scan.id).
- Regenerate the bundle from the original scan run instead of hand-editing it.
- If merging scans, merge at the scan level: keep each finding with its own scan record rather than cross-assigning findings.
- Check the importer (Sarif/Codex) invocation — ensure the source file corresponds to a single scan and wasn't corrupted in transit.
Example fix
// before (hand-edited bundle.json)
{ "scan": { "id": "scan-2" }, "findings": [{ "id": "f1", "scanId": "scan-1" }] }
// after
{ "scan": { "id": "scan-2" }, "findings": [{ "id": "f1", "scanId": "scan-2" }] } Defensive patterns
Strategy: validation
Validate before calling
const mismatched = bundle.findings.filter(f => f.scanId !== bundle.scan.id);
if (mismatched.length) throw new Error(`findings with foreign scanId: ${mismatched.map(f => f.id).join(", ")}`); Type guard
function hasConsistentScanIds(bundle: SecurityScanBundle): boolean {
return bundle.findings.every(f => f.scanId === bundle.scan.id);
} Try / catch
try {
const bundle = parseSecurityScanBundle(raw);
// use bundle
} catch (err) {
if (err instanceof Error && err.message.includes("belongs to")) {
logger.warn("bundle contains findings from another scan", { cause: err.message });
} else throw err;
} Prevention
- Never hand-edit scan bundle files; treat them as immutable scan output.
- When merging scans, keep findings paired with their own scan record.
- Run bundle validation as a post-processing step after any importer or transform.
When it happens
Trigger: Calling bundle(), readBundle(), importSarif(), or importCodexSecurityBundle() with a bundle JSON where one or more findings have scanId different from bundle.scan.id — e.g. hand-merged scan files, a copied scan record paired with another scan's findings, or an importer that misassigns scanId.
Common situations: Manually editing or concatenating scan output files under the security store; post-processing scripts that rewrite scan.id but not finding.scanId; importing SARIF produced by external tooling where run-to-finding linkage was reconstructed incorrectly.
Related errors
- Occurrence ${occurrence.id} references missing evidence: ${e
- lookbackDays must be a positive integer or 'all'
- Security scan contains duplicate finding ids
- Security scan manifest contains duplicate finding references
- Finding ${finding.id} contains duplicate evidence ids
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/eae47fa35eb22c0d.
Report an issue: GitHub.