Skip to content

Breaking change: referencing a component parameter with an inline schema silently renames generated types (regression from #2466) #2475

Description

@mromaszewicz

Summary

PR #2466 (merged to main) introduced an unintended, silent breaking change in generated type naming. When an operation references a component parameter ($ref: '#/components/parameters/X') whose schema is inline (an enum, an inline object, or an anyOf/oneOf), the generated helper type — previously named after the operation, e.g. GetItemsParamsStatus — is now named after the component parameter, e.g. StatusParam. Enum constant names change too, and lose their type prefix. Existing user code that referenced the old names no longer compiles, with no changelog entry or migration note.

This was first reported as a review comment on PR #2466.

Reproduction

# spec.yaml
openapi: 3.0.0
info: { title: t, version: "1.0" }
components:
  parameters:
    StatusParam:
      name: status
      in: query
      schema:
        type: string
        enum: [active, inactive]
paths:
  /items:
    get:
      operationId: getItems
      parameters:
        - $ref: '#/components/parameters/StatusParam'
      responses:
        '200': { description: ok }
# cfg.yaml
package: gen
generate: { models: true, client: true }
output: out.go

Before (commit 65742401, parent of #2466) vs After (a07731d8, merged #2466)

Before After
Params field Status *GetItemsParamsStatus Status *StatusParam
Enum type type GetItemsParamsStatus string type StatusParam string
Constants GetItemsParamsStatusActive, GetItemsParamsStatusInactive Active, Inactive

Any downstream code referencing GetItemsParamsStatus, GetItemsParamsStatusActive, etc. breaks. Separately, the new constants (Active, Inactive) drop the type prefix entirely, which raises the risk of constant-name collisions across enums in a package.

Root cause

The new lines in DescribeParameters (pkg/codegen/operations.go, the IsGoTypeReference(paramOrRef.Ref) branch):

pd.Schema.RefType = goType
pd.Schema.AdditionalTypes = nil
pd.Schema.UnionElements = nil

Clearing AdditionalTypes/UnionElements was necessary and correct for the anyOf/oneOf component-parameter case, which did not compile before #2466 (union member types were named from an empty path — N0/N1 — and never declared). For that case this is a strict broken→working fix, not a regression.

However, the same code path also catches the enum / inline-object case, which did compile before as GetItemsParamsStatus. For that case the change is a pure rename — the source of this breaking change.

Scope / why it went unnoticed

git show --stat a07731d8 shows the PR regenerated zero existing *.gen.go golden files (it only added the new internal/test/parameters/shared_anyof case). The repository's own test corpus does not exercise "operation references a component parameter that carries an inline schema", so the rename produced no diff in CI.

Note: the original review comment's example used a parameter whose schema is $ref: '#/components/schemas/Status'. That specific shape does not reproduce — output is identical before and after. The trigger is an inline schema on the referenced component parameter (enum / inline object / union), not a schema that is itself a $ref.

Proposed direction

To be fixed in a follow-up PR. Candidate approaches:

  1. Narrow the fix — only clear AdditionalTypes/UnionElements for anyOf/oneOf unions (the case that was genuinely broken), leaving enum/inline-object component parameters generating their prior operation-named types. Backward-compatible; preserves the Name path-level parameter helper types per operation #2466 anyOf fix.
  2. Opt-in flag — keep the cleaner shared naming but gate it, defaulting to the pre-Name path-level parameter helper types per operation #2466 names.
  3. Document as an intentional breaking change — accept the new (arguably cleaner) naming and add a changelog + migration note.

Regardless of approach, a golden-file test case covering "reference a component parameter with an inline enum/object/union" should be added so the naming contract is guarded going forward.

Regression introduced by #2466.

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