{"record":{"id":"87f565a881439f70","repo":"ComposioHQ/composio","slug":"invalid-beforeexecute-modifier-not-a-function","errorCode":null,"errorMessage":"Invalid beforeExecute modifier. Not a function.","messagePattern":"Invalid beforeExecute modifier\\. Not a function\\.","errorType":"exception","errorClass":"ComposioInvalidModifierError","httpStatus":null,"severity":"error","filePath":"ts/packages/core/src/models/Tools.ts","lineNumber":294,"sourceCode":"      tool,\n      { toolSlug, toolkitSlug, params },\n      modifiers?.beforeFileUpload,\n      requestOptions\n    );\n\n    // apply the before execute modifiers\n    if (modifiers?.beforeExecute) {\n      if (typeof modifiers.beforeExecute === 'function') {\n        modifiedParams = await modifiers.beforeExecute({\n          toolSlug,\n          toolkitSlug,\n          params: modifiedParams,\n        });\n        if (requestOptions?.signal?.aborted) {\n          throw new ComposioRequestCancelledError();\n        }\n      } else {\n        throw new ComposioInvalidModifierError('Invalid beforeExecute modifier. Not a function.');\n      }\n    }\n    return modifiedParams;\n  }\n\n  /**\n   * Applies schema-aware file preprocessing shared by direct and Tool Router\n   * session execution. This always runs before the caller's `beforeExecute`\n   * hook so the hook observes the exact arguments sent to the backend.\n   */\n  private async applyFileUploadModifiers(\n    tool: Tool,\n    {\n      toolSlug,\n      toolkitSlug,\n      params,\n    }: {\n      toolSlug: string;","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/ComposioHQ/composio/blob/64b1b85502b1beeb2379e6c9e8bf1104504fa637/ts/packages/core/src/models/Tools.ts#L276-L312","documentation":"ComposioInvalidModifierError thrown when the beforeExecute modifier provided to Tools.execute (or the modifiers config) is present but not a function. This is a config/type validation error, not a runtime API failure.","triggerScenarios":"Passing modifiers.beforeExecute as an object, string, or undefined-but-truthy value, e.g. { beforeExecute: { params: {...} } } or a class instance without call signature.","commonSituations":"Confusing the modifier argument shapes (passing config object instead of function); serializing modifiers accidentally; JS users bypassing type checks with as any.","solutions":["Pass a function: modifiers: { beforeExecute: async ({ params }) => ({ ...params, extra: 1 }) }.","If using TypeScript, remove any/as any so the compiler catches the wrong shape.","If no pre-execution transformation is needed, omit beforeExecute entirely."],"exampleFix":"// before\nawait tools.execute('T', params, { beforeExecute: { enabled: true } as any });\n\n// after\nawait tools.execute('T', params, { beforeExecute: async ({ params }) => params });","handlingStrategy":"type-guard","validationCode":"if (typeof modifiers?.beforeExecute !== 'function') throw new TypeError('beforeExecute must be a function');\nawait tools.execute(slug, params, modifiers);","typeGuard":"const isValidBeforeExecute = (m: unknown): m is (args: any) => any | Promise<any> =>\n  typeof m === 'function';","tryCatchPattern":"try { ... } catch (e) {\n  if (e instanceof ComposioInvalidModifierError) { /* fix modifier shape and retry */ }\n}","preventionTips":["Rely on TypeScript types for modifiers; avoid as any.","Omit beforeExecute when no transformation is needed."],"tags":["modifiers","validation","misuse","typescript"],"backgroundTag":"invalid-callback-argument","analyzedSha":"64b1b85502b1beeb2379e6c9e8bf1104504fa637","analyzedAt":"2026-08-28T15:39:33.623Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}