{"record":{"id":"1d2b3a030c801a1a","repo":"ComposioHQ/composio","slug":"trigger-subscription-error","errorCode":null,"errorMessage":"Trigger subscription error","messagePattern":"Trigger subscription error","errorType":"exception","errorClass":"PusherSubscriptionError","httpStatus":null,"severity":"error","filePath":"ts/packages/core/src/utils/pusher.ts","lineNumber":243,"sourceCode":"   * @example\n   * ```ts\n   * composio.trigger.subscribe((data) => {\n   *   console.log(data);\n   * });\n   * ```\n   */\n  static triggerSubscribe(clientId: string, fn: (data: TriggerData) => void): void {\n    try {\n      if (!PusherUtils.pusherClient) {\n        throw new Error('Pusher client not initialized');\n      }\n\n      const channel = PusherUtils.pusherClient.subscribe(`private-${clientId}_triggers`);\n\n      // Add subscription error handling\n      channel.bind('pusher:subscription_error', (data: Record<string, unknown>) => {\n        const error = data.error ? String(data.error) : 'Unknown subscription error';\n        throw new PusherSubscriptionError(`Trigger subscription error`, {\n          cause: error,\n        });\n      });\n\n      // Wrap the callback to handle errors\n      const safeCallback = (data: TriggerData) => {\n        try {\n          fn(data);\n        } catch (error: unknown) {\n          const errorMessage = error instanceof Error ? error.message : String(error);\n          logger.error('Error in trigger callback:', errorMessage);\n          // Don't throw here to prevent breaking the subscription\n        }\n      };\n\n      PusherUtils.bindWithChunking(\n        channel as PusherClient,\n        'trigger_to_client',","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/core/src/utils/pusher.ts#L225-L261","documentation":"Pusher emits pusher:subscription_error on a private channel when authorization fails or the channel cannot be joined. The SDK translates it into a PusherSubscriptionError('Trigger subscription error') with the underlying cause attached. For Composio, auth is done via your API key against {baseURL}/api/v3/internal/sdk/realtime/auth.","triggerScenarios":"Subscribing to private-{clientId}_triggers when the channel authorization POST fails: invalid/expired API key, wrong baseURL, network failure to the auth endpoint, or the backend rejecting the clientId.","commonSituations":"Expired or revoked Composio API key; pointing the SDK at the wrong environment/baseURL; clientId from a different workspace/project than the API key; auth endpoint returning non-JSON (proxy/HTML error page).","solutions":["Verify your Composio API key is valid and belongs to the same workspace as the clientId","Confirm baseURL matches the environment the clientId was created in","Inspect logger.debug output of the auth response body for the backend's rejection reason","Re-create the trigger/clientId if it was invalidated (e.g. deleted integration)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// validate auth prerequisites before subscribing\nif (!apiKey || !baseURL) throw new Error('Missing API credentials for realtime auth');","typeGuard":"const isPusherSubscriptionError = (e: unknown): boolean =>\n  e instanceof Error && e.constructor.name === 'PusherSubscriptionError';","tryCatchPattern":"try {\n  PusherUtils.triggerSubscribe(clientId, fn);\n} catch (e) {\n  if (isPusherSubscriptionError(e) && e.cause) {\n    logger.error('Auth rejected:', e.cause);\n    // rotate key or fix baseURL/clientId\n  }\n}","preventionTips":["Keep API key and clientId from the same workspace/environment","Enable debug logging to capture the auth response body","Re-create triggers after rotating keys or switching baseURL"],"tags":["pusher","authorization","realtime","triggers","api-key"],"backgroundTag":"channel-authorization-failed","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}