Skip to content

toolcraft-openapi-generate fails on OpenAPI 3.1 nullable types (anyOf with null) #285

@kamilio

Description

@kamilio

Problem

Running toolcraft-openapi-generate against an OpenAPI 3.1 / JSON Schema 2020-12 spec fails on nullable fields:

$ npm run generate
> toolcraft-openapi-generate --input https://www.i.quora.com/api/internal_agent/openapi.json --output src/generated --lock openapi.lock

Operation "patch_bot" uses unsupported requestBody.properties.display_name. JSON Schema composition keyword "anyOf" is not supported in v1.

Root cause

The spec's BotPatchRequest schema expresses nullable fields using the standard OpenAPI 3.1 syntax — anyOf with a null type variant:

{
  "BotPatchRequest": {
    "type": "object",
    "properties": {
      "display_name": {
        "anyOf": [
          { "type": "string" },
          { "type": "null" }
        ],
        "title": "Display Name"
      },
      "description":  { "anyOf": [{ "type": "string" },  { "type": "null" }] },
      "introduction": { "anyOf": [{ "type": "string" },  { "type": "null" }] },
      "allow_related_bot_recommendations": { "anyOf": [{ "type": "boolean" }, { "type": "null" }] },
      "picture_url":  { "anyOf": [{ "type": "string", "format": "uri", "minLength": 1, "maxLength": 2083 }, { "type": "null" }] }
    }
  }
}

This is the standard OpenAPI 3.1 way to express T | null (it replaces OpenAPI 3.0's nullable: true). Pydantic/FastAPI emits this shape by default for Optional[T] fields.

Every nullable field in the schema follows the same pattern, so even if display_name were special-cased, the next field would fail the same way.

Suggested fix

Recognize the anyOf: [T, {type: null}] (and the two-element variant in either order) shape as nullable T and lower it to whatever representation the generator already uses for nullables. Full anyOf support would be ideal, but the nullable case alone unblocks this spec.

Repro

  • Repo: poe-platform/poe-internal-agent-tools
  • Command: npm run generate
  • Input: https://www.i.quora.com/api/internal_agent/openapi.json

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions