can1357/oh-my-pi · error · Error
Codex Security bundle scan IDs do not agree
Error message
Codex Security bundle scan IDs do not agree
What it means
All three bundle documents must reference the same scan: manifest.scan.id must exist and both findings.json and coverage.json must carry the identical scanId. The importer throws when the IDs are missing or disagree, because merging documents from different scans would produce incorrect findings/coverage attribution.
Source
Thrown at packages/coding-agent/src/security/importers/codex-security.ts:210
const root = path.resolve(bundleDirectory);
const manifest = await readJson<CodexManifest>(path.join(root, "scan-manifest.json"));
const findingsDocument = await readJson<CodexFindingsDocument>(path.join(root, "findings.json"));
const coverageDocument = await readJson<CodexCoverageDocument>(path.join(root, "coverage.json"));
if (manifest.documentType !== "codex-security.scan-manifest" || manifest.schemaVersion !== "1.0") {
throw new Error("Unsupported Codex Security scan manifest");
}
if (findingsDocument.documentType !== "codex-security.findings" || findingsDocument.schemaVersion !== "1.0") {
throw new Error("Unsupported Codex Security findings document");
}
if (coverageDocument.documentType !== "codex-security.coverage" || coverageDocument.schemaVersion !== "1.0") {
throw new Error("Unsupported Codex Security coverage document");
}
if (
!manifest.scan?.id ||
findingsDocument.scanId !== manifest.scan.id ||
coverageDocument.scanId !== manifest.scan.id
) {
throw new Error("Codex Security bundle scan IDs do not agree");
}
const fixtureProvenance = await readJson<CodexFixtureProvenance>(path.join(root, "PROVENANCE.json")).catch(
(): CodexFixtureProvenance => ({}),
);
const scanId = options.createScanId?.() ?? createSecurityScanId();
const createdAt = options.createdAt ?? manifest.scan.startedAt ?? new Date().toISOString();
const canonicalRoot = await fs.realpath(path.resolve(options.repositoryRoot));
const producer: SecurityProducer = {
kind: "codex-security-bundle",
name: manifest.scan.producer?.name || "codex-security",
vendor: "openai",
};
if (manifest.scan.producer?.version !== undefined) producer.version = manifest.scan.producer.version;
if (fixtureProvenance.revision !== undefined) producer.revision = fixtureProvenance.revision;
if (fixtureProvenance.pluginVersion !== undefined) producer.pluginVersion = fixtureProvenance.pluginVersion;
const upstream: SecurityUpstreamProvenance = {};
if (fixtureProvenance.repository !== undefined) upstream.repository = fixtureProvenance.repository;
if (fixtureProvenance.revision !== undefined) upstream.revision = fixtureProvenance.revision;View on GitHub (pinned to 9690622007)
Solutions
- Re-export the full bundle from a single Codex Security scan so all three documents share one scanId
- Replace the mismatched file(s) with versions from the same run as the manifest
- Ensure the manifest includes a non-empty manifest.scan.id
Example fix
// before manifest.scan.id = "scan-111", findings.scanId = "scan-222" // after: regenerate so all documents carry "scanId": "scan-111"
Defensive patterns
Strategy: validation
Validate before calling
const [manifest, findings, coverage] = await Promise.all([
readJson(path.join(dir, "scan-manifest.json")),
readJson(path.join(dir, "findings.json")),
readJson(path.join(dir, "coverage.json")),
]);
const id = manifest.scan?.id;
if (!id || findings.scanId !== id || coverage.scanId !== id) {
throw new Error(`Scan ID mismatch: manifest=${id} findings=${findings.scanId} coverage=${coverage.scanId}`);
} Type guard
function scanIdsAgree(b: { manifest: { scan?: { id?: string } }; findings: { scanId: string }; coverage: { scanId: string } }): b is { manifest: { scan: { id: string } }; findings: { scanId: string }; coverage: { scanId: string } } {
const id = b.manifest.scan?.id;
return typeof id === "string" && id.length > 0 && b.findings.scanId === id && b.coverage.scanId === id;
} Try / catch
try {
const bundle = await importCodexSecurityBundle(dir);
} catch (err) {
if (err instanceof Error && err.message === "Codex Security bundle scan IDs do not agree") {
console.error("Bundle documents come from different scans — re-export the full bundle from one scan run");
} else throw err;
} Prevention
- Always export the complete bundle (manifest + findings + coverage + provenance) from a single run
- Delete the bundle directory between scan runs instead of overwriting individual files
- Assert scanId consistency in CI after bundle generation
- Never merge or copy documents between bundles
When it happens
Trigger: importCodexSecurityBundle where manifest.scan.id is absent, or findingsDocument.scanId !== manifest.scan.id, or coverageDocument.scanId !== manifest.scan.id — e.g. files from two different scan runs combined into one directory.
Common situations: Overwriting only part of a bundle directory across multiple scan runs; copying findings.json from run A with manifest/coverage from run B; generator bug omitting scan.id from the manifest.
Related errors
- Codex Security bundle locations must be repository-relative:
- Unsupported Codex Security scan manifest
- Unsupported Codex Security findings document
- Unsupported Codex Security coverage document
- Selected ${sourceName} session is no longer available
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/acc358e330f7289c.
Report an issue: GitHub.