Emit a clear error instead of crashing on duplicate generated schema names - #939
Merged
simonjbeaumont merged 2 commits intoAug 20, 2026
Merged
Conversation
Comment on lines
+28
to
+30
| let nodeLookup = nodes.reduce(into: [String: DeclarationRecursionDetector.Node]()) { lookup, node in | ||
| if lookup[node.name] == nil { lookup[node.name] = node } | ||
| } |
Collaborator
There was a problem hiding this comment.
Suggested change
| let nodeLookup = nodes.reduce(into: [String: DeclarationRecursionDetector.Node]()) { lookup, node in | |
| if lookup[node.name] == nil { lookup[node.name] = node } | |
| } | |
| let nodeLookup = Dictionary(nodes.map { ($0.name, $0) }, uniquingKeysWith: { first, _ in first }) |
Contributor
Author
There was a problem hiding this comment.
Thanks — updated the lookup to use Dictionary(_:uniquingKeysWith:) as suggested. Re-ran Test_translateSchemas (5 tests, 0 failures), the affected test surface (312 tests, 1 expected skip, 0 failures), strict swift-format, and git diff --check.
simonjbeaumont
requested changes
Aug 20, 2026
simonjbeaumont
left a comment
Collaborator
There was a problem hiding this comment.
Thanks for the PR. Mostly looks good. Made a suggestion to the dictionary build which seems a little obfuscated right now.
simonjbeaumont
enabled auto-merge (squash)
August 20, 2026 16:11
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
When the idiomatic naming strategy maps distinct OpenAPI component keys to the same generated Swift type name, schema translation currently reaches
Dictionary(uniqueKeysWithValues:)in recursive-type boxing and traps. This change detects duplicate generated top-level schema names before boxing and emits a deterministic error diagnostic with the documenteddefensivenaming andnameOverridesresolution paths.The defensive lookup in
translateBoxedTypeskeeps execution from reaching the duplicate-key dictionary initializer when a non-throwing diagnostic collector continues after the error. Duplicate basenames in different namespaces remain valid.Fixes #854.
Prior work and attribution
This continues the work from #907/#914 by Aditya Singh and incorporates the review feedback left there.
The original issue and reproduction were reported by @marknefedov in #854. Aditya Singh (
@adityasingh2400) implemented the substantial prior repair in #907 and #914. The placement intranslateSchemas, keepingtranslateBoxedTypesfocused on boxing, the single plural diagnostic path, and theA.T/B.Tnamespace countercase follow review direction from @simonjbeaumont on #914.The bug report and repair lineage are not original to this patch; this submission does not claim discovery or sole authorship.
Verification
Fatal error: Duplicate values for key: 'NullTime'.A.T/B.Trepository-native generated identitiesA.TPayload/B.TPayload: exit 0, no diagnostic.Test_translateSchemas: throwing collector, non-throwing collector, deterministic multiple collisions, and namespace countercase coverage.swift-format lintandgit diff --check: exit 0.Scope
Exactly three files change: two
_OpenAPIGeneratorCoreimplementation files and one focused test file. No public API or new architecture is introduced.