{"record":{"id":"a24807296c698ae3","repo":"ComposioHQ/composio","slug":"invalid-afterexecute-modifier-not-a-function","errorCode":null,"errorMessage":"Invalid afterExecute modifier. Not a function.","messagePattern":"Invalid afterExecute modifier\\. Not a function\\.","errorType":"exception","errorClass":"ComposioInvalidModifierError","httpStatus":null,"severity":"error","filePath":"ts/packages/core/src/models/Tools.ts","lineNumber":421,"sourceCode":"    if (this.autoUploadDownloadFiles) {\n      const fileToolModifier = new FileToolModifier(this.client, this.fileUploadPathOptions);\n      modifiedResult = await fileToolModifier.fileDownloadModifier(tool, {\n        toolSlug,\n        toolkitSlug,\n        result: modifiedResult,\n        signal: requestOptions?.signal,\n      });\n    }\n    // apply the after execute modifiers\n    if (modifier) {\n      if (typeof modifier === 'function') {\n        modifiedResult = await modifier({\n          toolSlug,\n          toolkitSlug,\n          result: modifiedResult,\n        });\n      } else {\n        throw new ComposioInvalidModifierError('Invalid afterExecute modifier. Not a function.');\n      }\n    }\n\n    return modifiedResult;\n  }\n\n  /**\n   * Lists Composio API tools available to the SDK.\n   *\n   * This method fetches remote Composio tools from the API in raw format. The response can be\n   * filtered and modified as needed. Local experimental custom tools are session-scoped; attach\n   * them when creating or reusing a Tool Router session, then use `session.tools()`,\n   * `session.customTools()`, or `session.execute()`.\n   * It provides access to the underlying tool data without provider-specific wrapping.\n   *\n   * @param {ToolListParams} query - Query parameters to filter the tools (required)\n   * @param {GetRawComposioToolsOptions} [options] - Optional configuration for tool retrieval\n   * @param {TransformToolSchemaModifier} [options.modifySchema] - Function to transform tool schemas","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/core/src/models/Tools.ts#L403-L439","documentation":"ComposioInvalidModifierError thrown by applyAfterExecuteModifiers when the afterExecute modifier configured on the tool/Composio instance is present but not a function. The SDK validates modifier callables before invoking them to avoid a less clear TypeError at call time.","triggerScenarios":"Passing a non-function afterExecute modifier, e.g. .with({ afterExecute: { fn: ... } }) or withModifiers({ afterExecute: null }) / a string / an object instead of a callback, then calling executeWithTool.","commonSituations":"Serializing modifiers from config/JSON, passing a modifier object shape from another SDK version, destructuring mistakes producing undefined wrapped in an object, copy-pasting modifier config from docs of a different version.","solutions":["Verify afterExecute is an async (result) => result-style function","Log typeof your afterExecute value before wiring it","Update to the current modifier signature: ({ toolSlug, toolkitSlug, result }) => result"],"exampleFix":"// before\n.with({ afterExecute: { result } => result })\n// after\n.with({ afterExecute: async ({ result }) => result })","handlingStrategy":"validation","validationCode":"if (typeof afterExecute !== 'function') throw new TypeError('afterExecute must be a function');","typeGuard":"const isModifierFn = (m: unknown): m is ({ result }: { result: unknown }) => Promise<unknown> => typeof m === 'function';","tryCatchPattern":"try { await tool.execute(args); } catch (e) { if (e instanceof ComposioInvalidModifierError) fixModifierConfig(); else throw e; }","preventionTips":["Type modifiers explicitly at the config boundary","Never load modifiers from JSON without a typeof check"],"tags":["modifiers","typescript","validation"],"backgroundTag":"invalid-callback-modifier","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}