openai/codex · error · anyhow::Error

expected ServerNotification schema to be an object

Error message

expected ServerNotification schema to be an object

What it means

A build-time assertion inside add_server_notification_emitted_at_to_json_schema: the generated JSON schema for ServerNotification must be a JSON object (map of properties) so an `emittedAt` field can be injected into it for TypeScript export. It fires when the schema generator produced a non-object (e.g. a boolean or bare type reference) for ServerNotification, meaning the protocol type changed in a way the export script no longer expects.

Solutions

  1. Inspect the generated schema value in export.rs and confirm why ServerNotification serializes to a non-object schema (e.g. an untagged alias or a `$ref`-only schema).
  2. Update the TS export (add #[ts] attributes or adjust the type) so ServerNotification generates a proper object schema with properties.
  3. If the injection is obsolete, guard the mutation on as_object_mut() succeeding instead of erroring.
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at codex-rs/app-server-protocol/src/export.rs:1377 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/1b968d3ae9e53c89. Report an issue: GitHub.

Appendix: source

Thrown at codex-rs/app-server-protocol/src/export.rs:1377

            .with_context(|| format!("Failed to write JSON schema for {file_stem}"))?;
    }

    let namespace = match raw_namespace {
        Some("v1") | None => None,
        Some(ns) => Some(ns.to_string()),
    };
    Ok(GeneratedSchema {
        in_v1_dir: raw_namespace == Some("v1"),
        namespace,
        logical_name: logical_name.to_string(),
        value: schema_value,
    })
}

fn add_server_notification_emitted_at_to_json_schema(schema: &mut Value) -> Result<()> {
    let schema = schema
        .as_object_mut()
        .ok_or_else(|| anyhow!("expected ServerNotification schema to be an object"))?;
    schema.insert(
        "properties".to_string(),
        serde_json::json!({
            "emittedAtMs": {
                "description": "Unix timestamp (in milliseconds) when app-server emitted this notification.",
                "format": "int64",
                "type": "integer"
            }
        }),
    );
    // Keep this optional in generated client schemas for compatibility with
    // older app-server versions. New servers still always emit it.
    Ok(())
}

fn enforce_numbered_definition_collision_overrides(schema_name: &str, schema: &mut Value) {
    for defs_key in ["definitions", "$defs"] {
        let Some(defs) = schema.get(defs_key).and_then(Value::as_object) else {

View on GitHub (pinned to 339751715c)