{"record":{"id":"3c9bb6c593879a6e","repo":"microsoft/aspire","slug":"result-error","errorCode":null,"errorMessage":"result.$error","messagePattern":"result\\.\\$error","errorType":"exception","errorClass":"CapabilityError","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/transport.mts","lineNumber":1054,"sourceCode":"\n            // Ref counting: The vscode-jsonrpc socket keeps Node's event loop alive.\n            // We ref() during RPC calls so the process doesn't exit mid-call, and\n            // unref() when idle so the process can exit naturally after all work completes.\n            if (this._pendingCalls === 0) {\n                this.socket?.ref();\n            }\n            this._pendingCalls++;\n\n            try {\n                const result = await this.connection.sendRequest(\n                    'invokeCapability',\n                    capabilityId,\n                    rpcArgs\n                );\n\n                // Check for structured error response\n                if (isAtsError(result)) {\n                    throw new CapabilityError(result.$error);\n                }\n\n                // Wrap handles automatically\n                return wrapIfHandle(result, this) as T;\n            } finally {\n                this._pendingCalls--;\n                if (this._pendingCalls === 0) {\n                    this.socket?.unref();\n                }\n            }\n        } finally {\n            for (const cancellationId of cancellationIds) {\n                unregisterCancellation(cancellationId);\n            }\n        }\n    }\n\n    disconnect(): void {","sourceCodeStart":1036,"sourceCodeEnd":1072,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/transport.mts#L1036-L1072","documentation":"When a capability RPC returns a structured AtsError payload (detected by isAtsError), the client throws a CapabilityError built from result.$error. This is the client-side projection of a server-side capability failure, preserving the structured error details.","triggerScenarios":"invokeCapability sends 'invokeCapability' over JSON-RPC and the .NET side responds with an error-shaped result (capability threw, validation failed server-side, resource not available) instead of a normal result value.","commonSituations":"Server-side capability throws an exception; invalid args pass client validation but fail server validation; referenced resource/handle no longer exists on the AppHost; capability deprecated or removed after regeneration mismatch.","solutions":["Catch CapabilityError and inspect its $error fields (message/code/details) to learn the server-side failure cause.","Validate the capability arguments against the generated types before calling.","Regenerate the TypeScript client if the AppHost API changed (capability renamed/removed).","Check the AppHost logs for the corresponding server-side exception stack."],"exampleFix":"// before\nconst result = await client.invokeCapability('myCap', { id }); // throws raw CapabilityError\n\n// after\ntry {\n  const result = await client.invokeCapability('myCap', { id });\n} catch (e) {\n  if (e instanceof CapabilityError) {\n    console.error('Capability failed:', e.$error.message, e.$error.code);\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"// validate against generated types before the call\nconst parsed = capabilityArgsSchema.safeParse(args);\nif (!parsed.success) throw new Error('invalid capability args');","typeGuard":"function isCapabilityError(e: unknown): e is CapabilityError {\n  return e instanceof CapabilityError;\n}","tryCatchPattern":"try {\n  return await client.invokeCapability(cap, args);\n} catch (e) {\n  if (isCapabilityError(e)) {\n    console.error('capability failed:', e.$error.code, e.$error.message);\n  }\n  throw e;\n}","preventionTips":["Catch CapabilityError specifically and surface $error details to users.","Validate arguments with generated schemas before invoking.","Regenerate the client when the AppHost API changes.","Check AppHost logs for the matching server-side exception."],"tags":["capability","rpc","server-error","typescript"],"backgroundTag":"api-error-response","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}