You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: @friendlyName on enum is skipped when enum is first referenced inside a template` #12345
Since TypeSpec 1.17.0, decorators on an enum can be skipped when the enum is first resolved through a property of a templated model.
In particular, @friendlyName is not applied. Consequently, the OpenAPI emitter uses the fully qualified TypeSpec name instead of the configured friendly name.
This appears to be a regression from TypeSpec 1.16.0.
This suggests that InTemplateDeclaration remains set while resolving a concrete enum reference. Enum declarations may be missing from the declarations that cause the checker to leave the template context.
This potentially affects decorators other than FriendlyName as well.
TypeSpec 1.17.0 can skip decorators on an enum when its first resolution occurs through a templated model property. This prevents @friendlyName metadata from reaching emitters and changes the generated OpenAPI schema name.
The behavior is most consistent with compiler checker state leaking template-declaration context while resolving the concrete enum. The enum then misses decorator evaluation, and @typespec/openapi3 falls back to the fully qualified name. The alias workaround changes resolution order and supports this diagnosis. The checker changes in #9588 are relevant to investigate, but duplicate searches found no issue describing this same regression.
📝 Suggested next steps
Add a compiler regression test covering first resolution of a decorated enum from a template declaration.
Verify other enum decorators are evaluated in the same path.
What is your goal here to have all models defined in Examples.Models to be flattened to the root of the service? A better solution might be an option in openapi3 emitter to toggle this scoping
Thanks, that clarification about the intended use of @friendlyName makes sense.
Our goal is not necessarily to flatten every model in Example.Models. These are public models provided by a TypeSpec library, and we want to preserve their existing OpenAPI component names for compatibility. An OpenAPI emitter option controlling namespace qualification could indeed be a better long-term solution.
However, I think there is a separate compiler regression behind this example. In 1.17, it appears that all decorators on a concrete enum are skipped when the enum is first resolved from within a template declaration, not only @friendlyName.
The behavior also changes when introducing an alias:
aliasAggregationTypeRef=AggregationType;
Using AggregationTypeRef inside the template causes the enum decorators to run again. This suggests that the concrete enum is resolved while InTemplateDeclaration is still set.
However, enums do not appear to be included among the concrete declarations that clear InTemplateDeclaration when followed through a type reference.
Would skipping every decorator on such an enum be considered expected? If not, I can reframe the issue around decorator execution rather than OpenAPI schema naming.
Activity
github-actions commentedon Oct 22, 2026
🎯 Issue Triage
TypeSpec 1.17.0 can skip decorators on an enum when its first resolution occurs through a templated model property. This prevents
@friendlyNamemetadata from reaching emitters and changes the generated OpenAPI schema name.Category: Bug
Area:
compiler:core🔗 [Playground Reproduction]((typespec.io/redacted)
📋 Reproduction code
🔍 Analysis
The behavior is most consistent with compiler checker state leaking template-declaration context while resolving the concrete enum. The enum then misses decorator evaluation, and
@typespec/openapi3falls back to the fully qualified name. The alias workaround changes resolution order and supports this diagnosis. The checker changes in #9588 are relevant to investigate, but duplicate searches found no issue describing this same regression.📝 Suggested next steps
timotheeguerin commentedon Oct 22, 2026
I think this is an unexpected behavior of friendlyName. That decorator was uniquely meant to be used on template to give each instance a name https://typespec.io/docs/standard-library/built-in-decorators/#@friendlyName.
What is your goal here to have all models defined in
Examples.Modelsto be flattened to the root of the service? A better solution might be an option in openapi3 emitter to toggle this scopingdalbrx-nitrobox commentedon Oct 22, 2026
Thanks, that clarification about the intended use of
@friendlyNamemakes sense.Our goal is not necessarily to flatten every model in
Example.Models. These are public models provided by a TypeSpec library, and we want to preserve their existing OpenAPI component names for compatibility. An OpenAPI emitter option controlling namespace qualification could indeed be a better long-term solution.However, I think there is a separate compiler regression behind this example. In 1.17, it appears that all decorators on a concrete enum are skipped when the enum is first resolved from within a template declaration, not only
@friendlyName.The behavior also changes when introducing an alias:
Using AggregationTypeRef inside the template causes the enum decorators to run again. This suggests that the concrete enum is resolved while InTemplateDeclaration is still set.
PR #11019 changed checkEnum to call:
However, enums do not appear to be included among the concrete declarations that clear InTemplateDeclaration when followed through a type reference.
Would skipping every decorator on such an enum be considered expected? If not, I can reframe the issue around decorator execution rather than OpenAPI schema naming.
timotheeguerin commentedon Oct 22, 2026
I see yeah no that does seem like a regression, Repro without friendlyName
playground
fix(compiler): preserve decorators on concrete types referenced from …