Skip to content

fix: Allow autopatch to resolve refs, when making the put schema optional - #1080

Open
lucaspopp-wbd wants to merge 7 commits into
danielgtaylor:mainfrom
lucaspopp-wbd:autopatch-refs
Open

fix: Allow autopatch to resolve refs, when making the put schema optional#1080
lucaspopp-wbd wants to merge 7 commits into
danielgtaylor:mainfrom
lucaspopp-wbd:autopatch-refs

Conversation

@lucaspopp-wbd

Copy link
Copy Markdown
Contributor

Pass the schema registry to autopatch's makeOptionalSchema method, so it can be leveraged to resolve refs

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.29%. Comparing base (22a3cb0) to head (a372dea).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1080      +/-   ##
==========================================
+ Coverage   93.22%   93.29%   +0.06%     
==========================================
  Files          23       23              
  Lines        4976     4997      +21     
==========================================
+ Hits         4639     4662      +23     
+ Misses        271      269       -2     
  Partials       66       66              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@wolveix

wolveix commented Jul 29, 2026

Copy link
Copy Markdown
Collaborator

Thanks for this. Two blockers before merge, both reproducible.

Stack overflow on recursive schemas. The deref at autopatch.go:458 is unconditional, so a self-referential type never terminates. This passes on 22a3cb0 and crashes at startup here (the old code survived only because it dropped refs):

type Node struct {
	Name     string  `json:"name"`
	Children []*Node `json:"children,omitempty"`
}
// register GET + PUT for Node, then AutoPatch(api) => fatal error: stack overflow

Nil panic on unresolvable refs. SchemaFromRef returns nil when the ref doesn't match the registry prefix (registry.go:174), so s goes nil and the literal at :462 panics:

makeOptionalSchema(registry, &huma.Schema{Ref: "https://example.com/schemas/Thing.json"})

A visited set handles both, matching how schema.go:702 and huma.go:556 already thread cycle guards:

if s.Ref != "" {
	resolved := registry.SchemaFromRef(s.Ref)
	if _, cycle := visited[s.Ref]; cycle || resolved == nil {
		// Unresolvable or self-referential: leave the ref in place.
		return &huma.Schema{Ref: s.Ref}
	}
	visited[s.Ref] = struct{}{}
	defer delete(visited, s.Ref)
	s = resolved
}

Keeping the ref on a cycle leaves nested required intact in that one spot, which beats crashing. Please add tests for both cases.

Minor:

  • :239 uses api.OpenAPI().Components.Schemas when oapi is already in scope.
  • AdditionalProperties is any and copied verbatim, so a *Schema there keeps its refs and its required.

@lucaspopp-wbd

Copy link
Copy Markdown
Contributor Author

@wolveix all great points! Addressed all of your feedback

@lucaspopp-wbd

Copy link
Copy Markdown
Contributor Author

Hey @wolveix wondering if you can take another look at this soon?

Would love to get this merged in so my team's SDK can leverage this!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants