Surface silent integration-assembly load failures (#16729)#17311
Conversation
When integration assembly discovery fails for any reason (build-pipeline version skew, stale local NuGet cache, transitive dependency mismatch, partially populated probe directory, etc.), the failure currently surfaces only as: No code generator found for language: TypeScript No language support found for: typescript/nodejs The underlying ReflectionTypeLoadException is swallowed at LogDebug, below the file logger's default Information threshold, and never reaches the CLI's on-disk log. This makes the user unable to self-diagnose. This change hardens the diagnostic chain at every layer without altering the success path: * CodeGeneratorResolver / LanguageSupportResolver now log ReflectionTypeLoadException at Warning level and include the LoaderExceptions text in the message. * When an assembly named Aspire.Hosting.CodeGeneration.* is loaded but contributes zero ICodeGenerator / ILanguageSupport types, log a Warning so the silent-failure case is visible. * AssemblyLoader runs an Aspire.TypeSystem version sanity check at startup against the libs directory and warns when the bundled and probed versions diverge. * LanguageService / CodeGenerationService error messages now list the available languages, or point at the apphost-server log + binary mismatch hint when zero have been discovered. * PrebuiltAppHostServer promotes apphost-server stdout/stderr capture from Trace to Debug/Information, so warnings emitted by the apphost server reach the default file log. Adds CodeGeneratorResolver.GetSupportedLanguages(), internal test-only constructors on both resolvers that take a synthetic assembly factory, and IntegrationLoadContext.GetSharedAssemblyNames(). Adds 8 new tests covering the resolver warning paths and the user-facing error messages. Closes #16729 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR improves diagnostics for integration-driven remote-host features (language support + code generation) so that silent integration assembly load/type discovery failures become visible in logs and produce actionable user-facing errors.
Changes:
- Promote
ReflectionTypeLoadExceptiondiscovery failures toWarningwith flattenedLoaderExceptions, and warn when a codegen assembly loads but contributes zero implementations. - Enhance RPC service error messages to list discovered languages, or (when none are discovered) point users to binary-mismatch/
LoaderExceptionswarnings in the apphost-server log. - Add startup warning for shared-assembly version mismatches (
Aspire.TypeSystem) and adjust CLI apphost-server stdout/stderr capture to reach default logs.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/Aspire.Hosting.RemoteHost.Tests/ServiceErrorMessageTests.cs | Adds coverage for improved user-facing error messages (but currently has constructor mismatch issues). |
| tests/Aspire.Hosting.RemoteHost.Tests/ResolverDiagnosticsTests.cs | Adds coverage for warning logs on type-load failures and “zero contributor” assemblies. |
| tests/Aspire.Hosting.RemoteHost.Tests/RecordingLogger.cs | Adds an in-memory logger helper for inspecting emitted log entries in tests. |
| src/Aspire.Hosting.RemoteHost/Language/LanguageSupportResolver.cs | Adds a test seam for injected assemblies and upgrades logging for type-load/contribution failures. |
| src/Aspire.Hosting.RemoteHost/Language/LanguageService.cs | Improves “no language support” errors with available-language listing / binary-mismatch guidance. |
| src/Aspire.Hosting.RemoteHost/IntegrationLoadContext.cs | Adds shared-assembly-name helper for alignment with loader policy. |
| src/Aspire.Hosting.RemoteHost/CodeGeneration/CodeGeneratorResolver.cs | Adds test seam + supported-languages enumeration + upgraded diagnostics. |
| src/Aspire.Hosting.RemoteHost/CodeGeneration/CodeGenerationService.cs | Improves “no code generator” errors with available-language listing / binary-mismatch guidance. |
| src/Aspire.Hosting.RemoteHost/AssemblyLoader.cs | Adds shared-assembly version mismatch warning at loader construction time. |
| src/Aspire.Cli/Projects/PrebuiltAppHostServer.cs | Promotes apphost-server stdout/stderr logging levels so warnings reach default logs. |
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17311Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17311" |
PR Testing CompleteResult: ✅ PR #17311 verified with caveats Dogfooded PR CLI
Key evidence from file logs: Cleanup: Temp workspace removed. |
| if (e.Data is not null) | ||
| { | ||
| _logger.LogTrace("PrebuiltAppHostServer({ProcessId}) stdout: {Line}", process.Id, e.Data); | ||
| // Promoted from LogTrace to LogDebug so that apphost-server stdout reaches the |
There was a problem hiding this comment.
having history type comments like this are awkward IMO. "Promoted from LogTrace to LogDebug" won't really mean anything in a few weeks. We should word this so it explains why we are doing what we are doing.
|
❓ CLI E2E Tests unknown — 94 passed, 0 failed, 2 unknown (commit View all recordings
📹 Recordings uploaded automatically from CI run #26167426720 |
…in aspire new Documents the improved diagnostics surfaced in microsoft/aspire#17311: - New error messages that list available languages when a specific language is not found - The binary-mismatch error message and guidance when no language support implementations are discovered at all - Resolution steps (aspire cache clear, checking the log for LoaderExceptions and version mismatch warnings) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Pull request created: #1024
|
|
📝 Documentation has been drafted in microsoft/aspire.dev#1024 targeting Added a Troubleshooting section to the
Note This draft PR needs human review before merging. |
Description
When
aspire new(or another integration-driven command) silently fails to find a code generator or language support — for any reason: build-pipeline version skew, a stale local NuGet cache, a transitive dependency mismatch, a partially populated probe directory, etc. — users see only this:The actual cause (e.g. a
ReflectionTypeLoadExceptionwhoseLoaderExceptionsdescribe anAspire.TypeSystemmismatch, or an integration assembly that was loaded but contributed zero discoverable types) is logged atLogDebug, which is below the file logger's defaultInformationthreshold and never reaches the on-disk log. Result: the user has no path to self-diagnose. Issue #16729 documents the symptom and the diagnostic-hardening direction the team agreed on after the originally-reported13.3.0reproduction turned out to be a local NuGet cache anomaly.This is diagnostic hardening only — no change to runtime binding behavior. After this PR, a recurrence of the same shape of failure surfaces a clear log entry naming the offending assembly and either the
LoaderExceptionstext or the bundled-vs-libs version mismatch, and the user-facing error message itself lists the available languages or points at the apphost-server log + binary-mismatch scenario.What users see after this PR
CLI log (file, default Information threshold):
User-facing error from the RPC service when there are some languages discovered but not the requested one:
User-facing error when no languages are discovered at all (the silent-failure case the issue is about):
Implementation summary
CodeGeneratorResolver/LanguageSupportResolver: promoteReflectionTypeLoadExceptionfromLogDebug→LogWarningwith flattenedLoaderExceptionstext. Add a per-assembly warning when anAspire.Hosting.CodeGeneration.*assembly is loaded but contributes zero impls (almost always a silent type-load failure).AssemblyLoader: addWarnIfSharedAssemblyMismatch, invoked at construction time. Compares the default-ALC version of each shared assembly (currently justAspire.TypeSystem) against the libs-on-disk version and logs aWarningon mismatch. This catches the case the version-unification logic inIntegrationLoadContext.Loadcan't help with — for the shared assembly, the load context unconditionally defers to the default ALC, so a probed/bundled mismatch never goes through version comparison.LanguageService/CodeGenerationService: replace bare"No language support found for: X"/"No code generator found for language: X"with a builder that lists available languages, or — when zero are discovered — explains the likely binary-mismatch cause and points at the apphost-server log.PrebuiltAppHostServer: promote spawned-processstdoutfromLogTrace→LogDebugandstderrfromLogTrace→LogInformation, so warnings emitted by the apphost server actually reach the default file log.Internal-only API additions
CodeGeneratorResolver.GetSupportedLanguages()— used byCodeGenerationServiceto list discovered languages in error messages.Func<IReadOnlyList<Assembly>>constructor on both resolvers, used by the new tests to inject synthetic assemblies without going through the file-system-probingAssemblyLoader.IntegrationLoadContext.GetSharedAssemblyNames()— single source of truth for "which assemblies does the integration ALC defer to default for", consumed by the newWarnIfSharedAssemblyMismatchinAssemblyLoader.All resolvers, services, and the load context are themselves
internal sealed. No public API surface is added.Validation
dotnet build src/Aspire.Hosting.RemoteHost/Aspire.Hosting.RemoteHost.csproj— 0 warnings, 0 errors.dotnet build src/Aspire.Cli/Aspire.Cli.csproj— 0 warnings, 0 errors.dotnet test --project tests/Aspire.Hosting.RemoteHost.Tests/Aspire.Hosting.RemoteHost.Tests.csproj -- --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"— 422 / 422 passed, including 8 new tests:ResolverDiagnosticsTests(4) — Warning logged onReflectionTypeLoadExceptionwithLoaderExceptionstext (both resolvers); zero-contributor warning fires for marker-named assemblies and does not fire for arbitrary ones.ServiceErrorMessageTests(4) —ScaffoldAppHostandGenerateCodeerror messages list discovered languages in the "some available" case and point at the binary-mismatch /LoaderExceptionshint in the "zero discovered" case.Relationship to the closed PR
This supersedes the closed #16733. The diagnostic-hardening half is unchanged in intent and lands cleanly. The
AssemblyLoadercall site needed adjustment becauseLoadAssembliesno longer carriesintegrationLibsPath; the warning now runs from the constructor wherelibsPathis in scope. Test helpers updated for the currentAssemblyLoader/LanguageService/CodeGenerationServiceconstructor shapes (which all now also takeRemoteHostProfilingTelemetry). The runtime binding fix the closed PR had originally explored is not included — the issue itself records that the originally-reported failure was a cache anomaly, not a binding regression.Fixes #16729
Checklist
<remarks />and<code />elements on your triple slash comments?