From ebe3d494cdeafc7939997f8f0bbed770275b0119 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 27 May 2026 03:32:07 +0000 Subject: [PATCH 1/3] Initial plan From 28ecae6c806f9e0d303fd8ffe5af9e5f83b38d87 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 27 May 2026 03:39:33 +0000 Subject: [PATCH 2/3] Fix TCGC crash when merged service has no version for depended lib Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com> --- ...ervice-dep-undefined-2026-05-27-03-38-0.md | 7 +++ .../src/decorators.ts | 17 ++++- .../test/clients/structure.test.ts | 62 +++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 .chronus/changes/fix-tcgc-multiple-service-dep-undefined-2026-05-27-03-38-0.md diff --git a/.chronus/changes/fix-tcgc-multiple-service-dep-undefined-2026-05-27-03-38-0.md b/.chronus/changes/fix-tcgc-multiple-service-dep-undefined-2026-05-27-03-38-0.md new file mode 100644 index 0000000000..b0105862e2 --- /dev/null +++ b/.chronus/changes/fix-tcgc-multiple-service-dep-undefined-2026-05-27-03-38-0.md @@ -0,0 +1,7 @@ +--- +changeKind: fix +packages: + - "@azure-tools/typespec-client-generator-core" +--- + +Fix "Cannot read properties of undefined" crash in the `inconsistent-multiple-service-dependency` validation when a service merged into a multi-service client does not specify a version for a depended library (e.g. its latest service version has no matching `@useDependency` entry). The validation now falls back to the latest version of the depended library, matching the behavior of downstream emitters. diff --git a/packages/typespec-client-generator-core/src/decorators.ts b/packages/typespec-client-generator-core/src/decorators.ts index 065d947377..9d09ce095a 100644 --- a/packages/typespec-client-generator-core/src/decorators.ts +++ b/packages/typespec-client-generator-core/src/decorators.ts @@ -33,7 +33,7 @@ import { isBody, isBodyRoot, } from "@typespec/http"; -import { resolveVersions } from "@typespec/versioning"; +import { getVersion, resolveVersions, type Version } from "@typespec/versioning"; import { AccessDecorator, AlternateTypeDecorator, @@ -274,8 +274,21 @@ function validateMultipleServiceDependencyVersions( for (const [depNs, depVersion] of resolutions[resolutions.length - 1].versions) { // Ignore versions of the merged services themselves. if (serviceSet.has(depNs)) continue; + // When the service does not specify a version for the depended library + // (e.g. the latest service version has no `@useDependency` mapping for it), + // fall back to the latest version of the depended library, matching the + // behavior expected by downstream emitters. + let resolvedDepVersion: Version | undefined = depVersion; + if (resolvedDepVersion === undefined) { + const depVersionMap = getVersion(program, depNs); + const allDepVersions = depVersionMap?.getVersions(); + if (allDepVersions && allDepVersions.length > 0) { + resolvedDepVersion = allDepVersions[allDepVersions.length - 1]; + } + } + if (resolvedDepVersion === undefined) continue; const versions = depVersions.get(depNs) ?? new Set(); - versions.add(depVersion.value ?? depVersion.name); + versions.add(resolvedDepVersion.value ?? resolvedDepVersion.name); depVersions.set(depNs, versions); } } diff --git a/packages/typespec-client-generator-core/test/clients/structure.test.ts b/packages/typespec-client-generator-core/test/clients/structure.test.ts index bb11071e0a..5890a1d937 100644 --- a/packages/typespec-client-generator-core/test/clients/structure.test.ts +++ b/packages/typespec-client-generator-core/test/clients/structure.test.ts @@ -2196,6 +2196,68 @@ it("no warning when multiple services share the same dependency version", async expectDiagnostics(diagnostics, []); }); +it("no crash when a merged service does not specify a version for the depended library", async () => { + // Regression test: when one of the merged services has a service version that + // does not map to any version of the depended library (i.e. no `@useDependency` + // for that service version), the validation should not crash with "Cannot read + // properties of undefined" and should fall back to the latest version of the + // depended library. + const [{ program }, diagnostics] = await SimpleBaseTester.compileAndDiagnose( + createClientCustomizationInput( + ` + @versioned(LibVersions) + namespace SharedLib { + enum LibVersions { + v1: "v1", + v2: "v2", + } + } + + @service + @versioned(VersionsA) + namespace ServiceA { + enum VersionsA { + @useDependency(SharedLib.LibVersions.v2) + av1, + } + op a(): void; + } + @service + @versioned(VersionsB) + namespace ServiceB { + enum VersionsB { + @useDependency(SharedLib.LibVersions.v2) + bv1, + bv2, + } + op b(): void; + }`, + ` + @client( + { + name: "CombineClient", + service: [ServiceA, ServiceB], + autoMergeService: true, + } + ) + namespace CombineClient {} + `, + ), + ); + await createSdkContextForTester(program); + // ServiceA explicitly uses SharedLib.v2; ServiceB does not specify a version + // so the validation falls back to SharedLib's latest version (v2). Both + // resolve to the same version, so no inconsistency warning is reported. + expectDiagnostics( + diagnostics.filter( + (d) => + d.code === + "@azure-tools/typespec-client-generator-core/inconsistent-multiple-service-dependency", + ), + [], + ); +}); + it("multiple clients from single service", async () => { const { program } = await SimpleBaseTester.compile( createClientCustomizationInput( From 21dbe0749a1c1148f4295d6b03d1937243927746 Mon Sep 17 00:00:00 2001 From: Chenjie Shi Date: Wed, 27 May 2026 13:16:03 +0800 Subject: [PATCH 3/3] Update structure.test.ts --- .../test/clients/structure.test.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/typespec-client-generator-core/test/clients/structure.test.ts b/packages/typespec-client-generator-core/test/clients/structure.test.ts index 5890a1d937..8161f925f0 100644 --- a/packages/typespec-client-generator-core/test/clients/structure.test.ts +++ b/packages/typespec-client-generator-core/test/clients/structure.test.ts @@ -2197,11 +2197,6 @@ it("no warning when multiple services share the same dependency version", async }); it("no crash when a merged service does not specify a version for the depended library", async () => { - // Regression test: when one of the merged services has a service version that - // does not map to any version of the depended library (i.e. no `@useDependency` - // for that service version), the validation should not crash with "Cannot read - // properties of undefined" and should fall back to the latest version of the - // depended library. const [{ program }, diagnostics] = await SimpleBaseTester.compileAndDiagnose( createClientCustomizationInput( `