Skip to content

Improve TypeScript AppHost missing-await errors#15106

Merged
sebastienros merged 2 commits intorelease/13.2from
fix-14724
Mar 11, 2026
Merged

Improve TypeScript AppHost missing-await errors#15106
sebastienros merged 2 commits intorelease/13.2from
fix-14724

Conversation

@sebastienros
Copy link
Copy Markdown
Contributor

Description

Improves the TypeScript AppHost experience when an async builder call is missing await.

This change adds Promise-like argument validation in the generated TypeScript transport so unresolved builder/resource promises are rejected before they cross JSON-RPC, and surfaces them as a user-facing AppHost Error with a helpful missing-await hint instead of a confusing internal capability/deserialization failure.

It also replaces the extra transport snapshot-only test with higher-level polyglot SDK coverage in TypeScriptCodegenValidationTests, which creates a TypeScript AppHost script with a missing await and verifies the resulting error message.

Validation:

  • ./dotnet.sh test tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests.csproj -- --filter-not-trait "quarantined=true" --filter-not-trait "outerloop=true"
  • ./dotnet.sh build tests/Aspire.Cli.EndToEnd.Tests/Aspire.Cli.EndToEnd.Tests.csproj
  • ./build.sh --build /p:SkipNativeBuild=true

Fixes #14724

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 10, 2026 16:17
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 10, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15106

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15106"

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the TypeScript AppHost developer experience by detecting unresolved Promise-like arguments before they cross JSON-RPC, then surfacing the problem as a user-facing “AppHost Error” with a missing-await hint (fixing the confusing internal capability/deserialization failure in #14724).

Changes:

  • Added Promise-like argument validation in the generated TypeScript transport and introduced AppHostUsageError for clearer user errors.
  • Updated generated SDK error handling to format AppHostUsageError as ❌ AppHost Error: in global rejection/exception handlers.
  • Replaced the transport snapshot-only coverage with an end-to-end CLI test that creates a TS AppHost missing an await and asserts the helpful error output.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/transport.ts Adds AppHostUsageError and validates capability args for Promise-like values before JSON-RPC invocation.
src/Aspire.Hosting.CodeGeneration.TypeScript/AtsTypeScriptCodeGenerator.cs Updates generated imports/exports and global error handling to recognize and format AppHostUsageError.
tests/Aspire.Cli.EndToEnd.Tests/TypeScriptCodegenValidationTests.cs Adds an end-to-end regression test that verifies the new missing-await hint.
tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/AtsGeneratedAspire.verified.ts Snapshot update to re-export AppHostUsageError and adjust error handling output.
tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts Snapshot update to re-export AppHostUsageError and adjust error handling output.
tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/transport.verified.ts Removes the transport snapshot (coverage moved to higher-level test).

Comment on lines +275 to +277
for (const [key, nestedValue] of Object.entries(value)) {
validateValue(nestedValue, `${path}.${key}`);
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validateCapabilityArgs currently recurses into any object via Object.entries(value). Some SDK types (e.g., ReferenceExpression / ResourceBuilderBase) are class instances that carry a _client reference and implement toJSON() for transport serialization; traversing them can walk into the AspireClient / socket object graph and add avoidable overhead on every capability call. Consider limiting recursion to plain JSON objects/arrays and treating non-plain objects (or objects with a toJSON() function) as atomic, or validating the result of toJSON() instead of enumerating instance fields.

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 10, 2026

🎬 CLI E2E Test Recordings

The following terminal recordings are available for commit ad3a4ec:

Test Recording
AddPackageInteractiveWhileAppHostRunningDetached ▶️ View Recording
AddPackageWhileAppHostRunningDetached ▶️ View Recording
AgentCommands_AllHelpOutputs_AreCorrect ▶️ View Recording
AgentInitCommand_DefaultSelection_InstallsSkillOnly ▶️ View Recording
AgentInitCommand_MigratesDeprecatedConfig ▶️ View Recording
AspireAddPackageVersionToDirectoryPackagesProps ▶️ View Recording
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps ▶️ View Recording
Banner_DisplayedOnFirstRun ▶️ View Recording
Banner_DisplayedWithExplicitFlag ▶️ View Recording
CreateAndDeployToDockerCompose ▶️ View Recording
CreateAndDeployToDockerComposeInteractive ▶️ View Recording
CreateAndPublishToKubernetes ▶️ View Recording
CreateAndRunAspireStarterProject ▶️ View Recording
CreateAndRunAspireStarterProjectWithBundle ▶️ View Recording
CreateAndRunJsReactProject ▶️ View Recording
CreateAndRunPythonReactProject ▶️ View Recording
CreateAndRunTypeScriptStarterProject ▶️ View Recording
CreateEmptyAppHostProject ▶️ View Recording
CreateStartAndStopAspireProject ▶️ View Recording
CreateTypeScriptAppHostWithViteApp ▶️ View Recording
DescribeCommandResolvesReplicaNames ▶️ View Recording
DescribeCommandShowsRunningResources ▶️ View Recording
DetachFormatJsonProducesValidJson ▶️ View Recording
DoctorCommand_DetectsDeprecatedAgentConfig ▶️ View Recording
DoctorCommand_WithSslCertDir_ShowsTrusted ▶️ View Recording
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted ▶️ View Recording
LogsCommandShowsResourceLogs ▶️ View Recording
PsCommandListsRunningAppHost ▶️ View Recording
PsFormatJsonOutputsOnlyJsonToStdout ▶️ View Recording
RestoreGeneratesSdkFiles ▶️ View Recording
RunWithMissingAwaitShowsHelpfulError ▶️ View Recording
SecretCrudOnDotNetAppHost ▶️ View Recording
SecretCrudOnTypeScriptAppHost ▶️ View Recording
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels ▶️ View Recording
StopAllAppHostsFromAppHostDirectory ▶️ View Recording
StopAllAppHostsFromUnrelatedDirectory ▶️ View Recording
StopNonInteractiveMultipleAppHostsShowsError ▶️ View Recording
StopNonInteractiveSingleAppHost ▶️ View Recording
StopWithNoRunningAppHostExitsSuccessfully ▶️ View Recording
TypeScriptAppHostWithProjectReferenceIntegration ❌ Upload failed

📹 Recordings uploaded automatically from CI run #22917251503

…ts.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@sebastienros sebastienros merged commit 8e632a0 into release/13.2 Mar 11, 2026
252 checks passed
@sebastienros sebastienros deleted the fix-14724 branch March 11, 2026 00:36
@dotnet-policy-service dotnet-policy-service bot added this to the 13.2 milestone Mar 11, 2026
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.

3 participants