Skip to content

@effect/platform: Nested anyOf emitted for flat union payloads in OpenAPI output #6052

@SimonVadier

Description

@SimonVadier

What version of Effect is running?

@effect/platform 0.94, effect 3.19

What steps can reproduce the bug?

  1. Define a flat Schema.Union(...) for a request payload.
  2. Use it as the payload for a single HTTP endpoint.
  3. Generate OpenAPI (or JSON Schema) from the HttpApi.
import * as Schema from "effect/Schema";
import * as HttpApi from "@effect/platform/HttpApi";
import * as HttpApiEndpoint from "@effect/platform/HttpApiEndpoint";

const A = Schema.Struct({ _tag: Schema.Literal("A"), a: Schema.String });
const B = Schema.Struct({ _tag: Schema.Literal("B"), b: Schema.Number });
const C = Schema.Struct({ _tag: Schema.Literal("C"), c: Schema.Boolean });

export const API = HttpApi.make("Demo").add(
  HttpApiGroup.make("Foo").add(
    HttpApiEndpoint.post("Bar", "/bar").setPayload(Schema.Union(A, B, C)),
  ),
);

// Generate OpenAPI / JSON Schema from `api`
// Expected: anyOf: [A, B, C]
// Actual: anyOf: [ anyOf: [ anyOf: [A, B], C ] ] (nested)

What is the expected behavior?

The request body schema should have a flat anyOf array with the union members:

anyOf: [A, B, C]

What do you see instead?

The request body schema is encoded as a recursive/left-associated anyOf, e.g.:

anyOf: [ anyOf: [A, B ], C ] (or deeper nesting with more members)

Additional information

It looks like union members are merged incrementally (union of union), and the JSON Schema encoder preserves the AST shape. This is still valid JSON Schema but makes the output much harder to read and diff. There’s already UnionUnifyAST in @effect/platform which flattens unions

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions