{"record":{"id":"e5ea0ec146512ec1","repo":"ComposioHQ/composio","slug":"userid-is-required-when-custom-tools-are-bound-to","errorCode":null,"errorMessage":"userId is required when custom tools are bound to a session.","messagePattern":"userId is required when custom tools are bound to a session\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ts/packages/core/src/models/ToolRouterSession.ts","lineNumber":143,"sourceCode":"  public warnings: ToolRouterSessionWarning[];\n  private readonly preloadedCustomToolSlugs: string[];\n  private readonly inlineCustomToolsPayload: ToolRouterSessionMetadata['inlineCustomToolsPayload'];\n\n  /** Singleton session context — shared across all custom tool executions */\n  private readonly sessionContext?: SessionContext;\n\n  constructor(\n    private readonly client: ComposioClient,\n    private readonly config: ComposioConfig<TProvider> | undefined,\n    sessionId: string,\n    mcp: ToolRouterMCPServerConfig,\n    experimentalOverrides?: Pick<SessionExperimental, 'assistivePrompt'>,\n    private readonly customToolsMap?: CustomToolsMap,\n    private readonly userId?: string,\n    metadata?: ToolRouterSessionMetadata\n  ) {\n    if (customToolsMap && !userId) {\n      throw new Error('userId is required when custom tools are bound to a session.');\n    }\n    this.sessionId = sessionId;\n    this.mcp = mcp;\n    this.experimental = {\n      assistivePrompt: experimentalOverrides?.assistivePrompt,\n      files: new ToolRouterSessionFilesMount(client, sessionId),\n    };\n    this.preload = metadata?.preload ?? { tools: [] };\n    this.sandbox = metadata?.workbench;\n    this.configVersion = metadata?.configVersion;\n    this.warnings = metadata?.warnings ?? [];\n    this.preloadedCustomToolSlugs = metadata?.preloadedCustomToolSlugs ?? [];\n    this.inlineCustomToolsPayload = metadata?.inlineCustomToolsPayload;\n\n    // Create singleton session context if custom tools are bound\n    if (customToolsMap && userId) {\n      this.sessionContext = new SessionContextImpl(\n        client,","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/core/src/models/ToolRouterSession.ts#L125-L161","documentation":"The ToolRouterSession constructor enforces that any session bound to a custom tools map must also carry a userId, because the backend needs a stable per-user identity to route and hydrate custom tools. Missing userId is a hard construction-time error.","triggerScenarios":"Internally constructing (via SDK flows like session hydration) a ToolRouterSession with a customToolsMap but no userId — typically caused by user code creating sessions with custom tools while omitting the userId parameter in the session/config options.","commonSituations":"Adding custom tools to a session config and forgetting to pass userId; multi-user server where userId plumbing was skipped in one code path; upgrading to an SDK version that made userId mandatory with custom tools.","solutions":["Pass userId whenever custom tools are bound: composio.sessions.create({ userId, ... })","If you don't need custom tools on that session, remove them so the map isn't bound","Audit all session-creation call sites for a consistent userId"],"exampleFix":"// before\nawait composio.sessions.create({ tools: [customTool] });\n// after\nawait composio.sessions.create({ userId: 'user-42', tools: [customTool] });","handlingStrategy":"validation","validationCode":"const usesCustomTools = tools.some(t => isCustomTool(t));\nif (usesCustomTools && !userId) throw new Error('userId required with custom tools');\nawait composio.sessions.create({ userId, tools });","typeGuard":"const needsUserId = (tools: unknown[]): boolean => tools.some(isCustomTool);","tryCatchPattern":"try { const s = await composio.sessions.create(cfg); } catch (e) { if (/userId is required/.test(String(e?.message))) { return composio.sessions.create({ ...cfg, userId: currentUserId }); } throw e; }","preventionTips":["Always pass userId when configuring custom tools","Centralize session creation in one helper that enforces userId","Add a lint/review rule for custom-tool configs"],"tags":["session","custom-tools","user-id","typescript"],"backgroundTag":"missing-required-parameter","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}