{"record":{"id":"d781bedda34236ee","repo":"microsoft/aspire","slug":"not-connected-to-apphost","errorCode":null,"errorMessage":"Not connected to AppHost","messagePattern":"Not connected to AppHost","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/transport.mts","lineNumber":1028,"sourceCode":"    }\n\n    /**\n     * Invoke an ATS capability by ID.\n     *\n     * Capabilities are operations exposed by [AspireExport] attributes.\n     * Results are automatically wrapped in Handle objects when applicable.\n     *\n     * @param capabilityId - The capability ID (e.g., \"Aspire.Hosting/createBuilder\")\n     * @param args - Arguments to pass to the capability\n     * @returns The capability result, wrapped as Handle if it's a handle type\n     * @throws CapabilityError if the capability fails\n     */\n    async invokeCapability<T = unknown>(\n        capabilityId: string,\n        args?: Record<string, unknown>\n    ): Promise<T> {\n        if (!this.connection) {\n            throw new Error('Not connected to AppHost');\n        }\n\n        validateCapabilityArgs(capabilityId, args);\n        const cancellationIds: string[] = [];\n\n        try {\n            const rpcArgs = await marshalTransportValue(args ?? null, this, cancellationIds, capabilityId);\n\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(","sourceCodeStart":1010,"sourceCodeEnd":1046,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.CodeGeneration.TypeScript/Resources/transport.mts#L1010-L1046","documentation":"invokeCapability requires an established connection stored in this.connection. If the client is not connected (never connected, disconnected, or connect failed), it throws 'Not connected to AppHost' before validating or sending anything.","triggerScenarios":"Calling invokeCapability on a new AspireClient before awaiting connect(); after the socket closed (onConnectedSocketClose fired); after a failed authentication left connection null; calling from a different client instance than the one connected.","commonSituations":"Race where code runs before connect() resolves; connection lost mid-session due to AppHost shutdown or network drop; error during connect swallowed so the app continues invoking capabilities.","solutions":["Await client.connect() and confirm it succeeds before invoking capabilities.","Check socket close/error handlers to detect disconnection and reconnect before retrying invokeCapability.","Ensure you invoke on the same client instance that performed the connection.","Add a ready/connected guard or state check around capability calls in your app logic."],"exampleFix":"// before\nconst client = new AspireClient();\nclient.connect(); // not awaited\nconst result = await client.invokeCapability('cap', {});\n\n// after\nconst client = new AspireClient();\nawait client.connect();\nif (!client.isConnected) throw new Error('connect failed');\nconst result = await client.invokeCapability('cap', {});","handlingStrategy":"validation","validationCode":"if (!client.connection) {\n  throw new Error('call await client.connect() before invokeCapability');\n}","typeGuard":"function isConnected(c: AspireClient): boolean {\n  return c.connection !== null;\n}","tryCatchPattern":"try {\n  const result = await client.invokeCapability(cap, args);\n} catch (err) {\n  if (String(err.message) === 'Not connected to AppHost') {\n    await client.connect();\n    return client.invokeCapability(cap, args);\n  }\n  throw err;\n}","preventionTips":["Always await connect() and check readiness before any capability call.","Subscribe to socket close/error events to track connection state.","Serialize startup: no capability calls until the connect promise resolves.","Reuse a single connected client instance application-wide."],"tags":["connection","state","typescript"],"backgroundTag":"not-connected","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"}