GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Propagate one-sided type and format in allOf merges by mromaszewicz · Pull Request #2526 · oapi-codegen/oapi-codegen

Conversation

@mromaszewicz

@mromaszewicz mromaszewicz commented Aug 16, 2026

Copy link
Copy Markdown
Member

Fixes #2524.

Problem

mergeOpenapiSchemas only errored on a type conflict when both members declared a type; otherwise it kept the first member's type, silently discarding the second's. Because allOf members merge pairwise in order, the generated Go shape depended on member ordering (see the issue for the repro — a struct in one order, any in the other).

Format had the mirror-image problem: any mismatch errored, including set-vs-unset, so the allOf decorator idiom over a $ref to a format-carrying scalar failed generation outright:

NullableUuid:
  allOf:
    - $ref: "#/components/schemas/Uuid"   # type: string, format: uuid
    - description: decorated              # no format -> "can not merge incompatible formats"

Fix

Both fields now follow the same one-sidedness rule: when exactly one member declares a type/format, it propagates to the merged schema; when both declare and they differ, the existing errors remain.

Compatibility notes

  • Repo-wide make generate changes no existing committed .gen.go — the entire test corpus is unaffected.
  • The format half is purely additive: specs that previously failed generation now work.
  • The type half changes output only for specs whose allOf mixes a typeless member with a non-object-typed member — output there was order-dependent (and per JSON Schema semantics, wrong: properties doesn't constrain non-object instances, so allOf: [{properties…}, {type: string}] only ever validates strings). Specs hiding two conflicting types behind a typeless member (e.g. [{properties…}, {type: string}, {type: number}]) now hit the existing incompatible-types error instead of silently generating a struct; such specs are unsatisfiable. compatibility.old-merge-schemas routes to the untouched legacy codepath and remains the escape hatch.

Tests

  • Unit tests in merge_schemas_test.go for both propagation rules, order symmetry, and the preserved error cases.
  • Conformance fixtures in internal/test/aggregates/allof/: the issue's repro in both member orders (both lower to any), single-type in both orders (both lower to string), and the format-decorator idiom in both orders (both lower to openapi_types.UUID), pinned by TestIssue2524.

make tidy && make test && make generate && make lint all pass.

🤖 Generated with Claude Code

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

greptile-apps[bot] reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@mromaszewicz @claude
Propagate one-sided type and format in allOf merges
7dc86b5
MergeSchemas only errored on a type conflict when both members declared a
type; otherwise it kept the first member's type, silently discarding the
second's. Because allOf members merge pairwise in order, the generated Go
shape depended on member ordering. Format had the mirror-image problem:
any mismatch errored, including set-vs-unset, which broke the allOf
decorator idiom over refs to format-carrying scalars.

Both now follow the same rule: when exactly one member declares a
type/format it propagates to the merged schema; when both declare and
they differ, the existing errors remain.

Fixes oapi-codegen#2524

Co-Authored-By: Claude Fable 5 <[email protected]>
@mromaszewicz
mromaszewicz requested a review from a team as a code owner August 16, 2026 14:53
@mromaszewicz mromaszewicz added the bug Something isn't working label Aug 16, 2026
@greptile-apps

greptile-apps Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR makes the current allOf merger propagate a type or format declared by only one member while preserving errors for conflicting declarations.

  • Adds symmetric unit coverage for one-sided type and format propagation.
  • Adds allOf conformance fixtures covering primitive, union, and UUID decorator cases in both member orders.
  • Updates committed generated output to pin the corrected generated Go shapes.

Confidence Score: 5/5

The PR appears safe to merge with no actionable correctness, security, or maintainability issues identified.

The merge logic handles absent declarations symmetrically, retains conflict errors when both members declare incompatible values, preserves the legacy compatibility path, and includes focused unit and generated-output regression coverage.

Important Files Changed

Filename Overview
pkg/codegen/merge_schemas.go Propagates one-sided type and format values during current-path allOf merging while retaining explicit conflict detection.
pkg/codegen/merge_schemas_test.go Adds focused tests for symmetric propagation, unchanged typeless behavior, and preserved type/format conflict errors.
internal/test/aggregates/allof/spec_new_merge.yaml Adds category-appropriate regression schemas for order-independent primitive, union, and format-carrying allOf merges.
internal/test/aggregates/allof/allof_test.go Adds compile-time shape checks for the newly generated aliases.
internal/test/aggregates/allof/allof_new_merge.gen.go Contains the expected generated string, any, and UUID aliases without unrelated generated-code drift.

Reviews (1): Last reviewed commit: "Propagate one-sided type and format in a..." | Re-trigger Greptile

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@mromaszewicz
mromaszewicz merged commit 5a6c494 into oapi-codegen:main Aug 16, 2026
15 checks passed

Uh oh!

There was an error while loading. Please reload this page.

This was referenced Aug 19, 2026
Cover remaining OpenAPI 3.1 union test positions #2530
Merged
fix: handle untyped strict response bodies #2514
Merged
@mromaszewicz
mromaszewicz deleted the fix/allof-type-format-propagation branch September 26, 2026 00:46
mromaszewicz pushed a commit that referenced this pull request Nov 9, 2026
@bendrucker
Cover remaining OpenAPI 3.1 union test positions (#2530)
e77fc90
* Cover remaining OpenAPI 3.1 union positions in the conformance suites

The review of #2522 asked for the untested union positions to be
committed. Three surfaces had no conformance coverage:

- array items: a named array component whose items are a union lowers to
  a []any alias and round-trips mixed member values
- a union as a oneOf branch: the outer schema keeps the standard union
  machinery with the branch accessor typed any, whose As... conversion
  can never fail, so branch discrimination falls to the caller
- response headers: ResponseHeaderDefinition.SchemaTypes() feeds the
  Types list the generated ClientWithResponses passes when binding
  declared response headers, previously exercised by no test

The allOf position is already pinned by the spec added in #2526 (both
member orderings), so it is deliberately not duplicated here.

* Tighten comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

bug Something isn't working

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

MergeSchemas silently drops a member's type when an earlier allOf member has none (order-dependent output)

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@mromaszewicz
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.