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

  1. Re-export the full bundle from a single Codex Security scan so all three documents share one scanId
  2. Replace the mismatched file(s) with versions from the same run as the manifest
  3. 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

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


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