Repository navigation
Description
When a oneOf or anyOf branch is a $ref to a whole file ($ref: ./user.yaml, no # fragment), the union's As*/From*/Merge* accessors are named after the branch's inline Go type, so the generated code has methods like AsStruct {\n Name *string ... }() and formatting fails.
Whole-file refs are otherwise generated inline (IsGoTypeReference returns false for them, #308): the same file used directly as a body schema or as a property works, and an inline branch (- {type: object, properties: ...}) in the same union gets its own type, GetItems200JSONResponseBody0.
Reproduction
openapi.yaml:
openapi: 3.0.3
info: {title: t, version: "1"}
paths:
/items:
get:
responses:
"200":
description: ok
content:
application/json:
schema:
oneOf:
- $ref: ./user.yaml
- $ref: ./group.yamluser.yaml:
type: object
properties:
name: {type: string}group.yaml:
type: object
properties:
id: {type: integer}$ oapi-codegen -generate types -package api -o api.gen.go openapi.yaml
error generating code: error formatting Go code at line 53: api.go:53:5: expected declaration, found Name (and 2 more errors)No configuration file. The unformatted output (with output-options: skip-fmt: true) shows where it breaks:
// AsStruct {
Name *string`json:"name,omitempty"`
} returns the union data inside the GetItems200JSONResponseBody as a struct {
Name *string`json:"name,omitempty"`
}
func (t GetItems200JSONResponseBody) AsStruct {
Name *string`json:"name,omitempty"`
}() (struct {The same happens with anyOf, with only one branch being a whole-file ref, with openapi: 3.1.0, for a property's oneOf, and for a component schema (components.schemas.Item: {oneOf: [$ref: ./user.yaml, $ref: ./group.yaml]}, referenced from the response). The component form fails the same way on v2.4.1 through v2.6.0; the inline body form has failed since v2.7.0, when inline body unions started getting accessors.
Expected
The branches are generated like inline ones: GetItems200JSONResponseBody0 and GetItems200JSONResponseBody1, with AsGetItems200JSONResponseBody0() and so on, and the code compiles. Or, if whole-file refs aren't meant to be supported as union branches, an error that says so.
Versions
v2.8.1 and main (15f5714, v2.8.1-0.20261028140811-15f571472ff8, error at line 56 there), Go 1.27.3, linux/amd64.
Likely cause
generateUnionElement (pkg/codegen/union.go:88 on main) names and defines a branch only when element.Ref == "". A whole-file ref has a non-empty Ref, but generateGoSchema inlined it, so its GoType is the struct literal. Checking !IsGoTypeReference(element.Ref) there instead makes both forms above generate the ...0/...1 types, and the output compiles; I haven't run the test suite on that change.
Activity
n-hiraha commentedon Oct 30, 2026
I reproduced this on
main(15f5714) on darwin/arm64 with the exact files above (same error, at line 56).The change you suggested in
generateUnionElement, checking!IsGoTypeReference(element.Ref)instead ofelement.Ref == "", fixes it for me. The output hasGetItems200JSONResponseBody0/GetItems200JSONResponseBody1withAsGetItems200JSONResponseBody0()etc., the generated package passesgo vet, andgo test ./pkg/codegen/...passes.I haven't run the full suite yet (the
internal/testmodule andmake generate).Are you planning to open a PR for this? If not, I'd be happy to put one up with a regression test covering the response-body, property, and component-schema forms you listed, and credit you for the diagnosis.
BogdanYarotsky commentedon Oct 30, 2026
Hi @n-hiraha, please, go ahead with the PR. I am fine with it 🙂 Thank you!