openai/codex · error · anyhow::Error
expected v2 namespace in bundle definitions
Error message
expected v2 namespace in bundle definitions
What it means
Third guard in build_flat_v2_schema: it requires definitions["v2"] to be an object, since its whole job is lifting the v2 namespace to the root definitions map for Python codegen. The merge step namespaces all v2 request, response, and notification schemas under definitions.v2, so a missing or non-object v2 means the bundle carries no v2 API surface at all.
Source
Thrown at codex-rs/app-server-protocol/src/export.rs:1100
/// a direct feed would treat `v2` itself as a schema and miss unreferenced v2
/// leaves. This helper flattens all v2 definitions to the root definitions map,
/// then pulls in the shared root schemas and any non-v2 transitive deps they
/// still reference. Keep the shared root unions intact here: some valid
/// request/notification/event variants are inline or only reference shared root
/// helpers, so filtering them by the presence of a `#/definitions/v2/` ref
/// would silently drop real API surface from the flat bundle.
fn build_flat_v2_schema(bundle: &Value) -> Result<Value> {
let Value::Object(root) = bundle else {
return Err(anyhow!("expected bundle root to be an object"));
};
let definitions = root
.get("definitions")
.and_then(Value::as_object)
.ok_or_else(|| anyhow!("expected bundle definitions map"))?;
let v2_definitions = definitions
.get("v2")
.and_then(Value::as_object)
.ok_or_else(|| anyhow!("expected v2 namespace in bundle definitions"))?;
let mut flat_root = root.clone();
let title = root
.get("title")
.and_then(Value::as_str)
.unwrap_or("CodexAppServerProtocol");
let mut flat_definitions = v2_definitions.clone();
let mut shared_definitions = Map::new();
let mut non_v2_refs = HashSet::new();
for shared in FLAT_V2_SHARED_DEFINITIONS {
let Some(shared_schema) = definitions.get(*shared) else {
continue;
};
let shared_schema = shared_schema.clone();
non_v2_refs.extend(collect_non_v2_refs(&shared_schema));
shared_definitions.insert((*shared).to_string(), shared_schema);
}View on GitHub (pinned to 339751715c)
Solutions
- Ensure at least one v2 schema lands under definitions.v2 before flattening: check the v2 emitters and the retain filters in generate_json_with_experimental.
- In tests, include a non-empty v2 object in the fixture's definitions.
- If it regressed outside tests, bisect changes to the export_client_* / export_server_* schema emitters and the namespace insertion logic.
Example fix
// before
let bundle = json!({"definitions": {}}); // no v2 namespace: error
// after
let bundle = json!({"definitions": {
"v2": {"thread/start/params": {"type": "object"}}
}}); Defensive patterns
Strategy: type-guard
Validate before calling
// Call-site check before flattening:
if !has_v2_namespace(&bundle) {
return Err(anyhow!("bundle has no v2 namespace; check the v2 schema emitters"));
} Type guard
fn has_v2_namespace(v: &serde_json::Value) -> bool {
v.get("definitions")
.and_then(|d| d.get("v2"))
.is_some_and(serde_json::Value::is_object)
} Prevention
- Assert the v2 namespace is non-empty in export tests so silent emitter loss fails early.
- When gating or filtering schemas, verify at least one v2 emitter survives the filter.
- Treat this guard as a pipeline invariant: fix the emitters, never bypass the check.
When it happens
Trigger: generate_json_with_experimental reaching the flattener with zero namespaced v2 schemas, for example when v2 emitters produced nothing or earlier retain filters dropped every v2 entry; or test bundles whose definitions map has no v2 key.
Common situations: Refactors that stop exporting v2 types or rename the namespace; fixtures built only from v1 types; experimental gating or allowlist filters that accidentally exclude all v2 emitters.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- expected bundle root to be an object
- expected bundle definitions map
- TypeScript header worker panicked
- Prettier failed with status {status}
- generated input schema for {name} should parse: {err}
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/b1cfe3ded7f61e2b.
Report an issue: GitHub.