{"record":{"id":"ad7a9ba01aed57b7","repo":"gitroomhq/postiz-app","slug":"tool-not-found","errorCode":null,"errorMessage":"Tool not found","messagePattern":"Tool not found","errorType":"http","errorClass":"HttpException","httpStatus":404,"severity":"error","filePath":"apps/backend/src/public-api/routes/v1/public.integrations.controller.ts","lineNumber":588,"sourceCode":"\n    const integrationProvider = socialIntegrationList.find(\n      (p) => p.identifier === getIntegration.providerIdentifier\n    )!;\n\n    if (!integrationProvider) {\n      throw new HttpException({ msg: 'Integration provider not found' }, 404);\n    }\n\n    const tools = this._integrationManager.getAllTools();\n    if (\n      // @ts-ignore\n      !tools[integrationProvider.identifier]?.some(\n        (p: any) => p.methodName === body.methodName\n      ) ||\n      // @ts-ignore\n      !integrationProvider[body.methodName]\n    ) {\n      throw new HttpException({ msg: 'Tool not found' }, 404);\n    }\n\n    while (true) {\n      try {\n        // @ts-ignore\n        const result = await integrationProvider[body.methodName](\n          getIntegration.token,\n          body.data || {},\n          getIntegration.internalId,\n          getIntegration\n        );\n\n        return { output: result };\n      } catch (err) {\n        if (err instanceof RefreshToken) {\n          const data = await this._refreshIntegrationService.refresh(\n            getIntegration\n          );","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/apps/backend/src/public-api/routes/v1/public.integrations.controller.ts#L570-L606","documentation":"The requested tool (methodName) is rejected unless it appears both in the integration manager's registered tools for that provider identifier AND exists as a callable member on the provider class. If either check fails, the API returns 404 'Tool not found'. This guards against invoking arbitrary method names on provider objects.","triggerScenarios":"POST to triggerIntegrationTool with a methodName that is not a registered tool (typo, wrong casing, wrong provider), or a tool that exists in code but is not registered via _integrationManager.getAllTools() for that provider in the running build.","commonSituations":"Calling a method that belongs to a different channel (e.g. a Discord-only tool on a Slack integration); methodName casing mismatch ('SendPost' vs 'sendPost'); tool added in a newer version than the deployed backend; using internal method names that are not exposed as tools.","solutions":["Fetch the available tools from the integration manager / provider metadata and only call methods present for that provider identifier","Check exact methodName casing and spelling against the provider's tool definitions","Upgrade the backend if the tool was introduced in a newer release","Confirm the tool is valid for the integration's channel type"],"exampleFix":"// before\nawait triggerTool(integration.id, 'publishNow', {...}); // 404\n\n// after\nconst tools = await getProviderTools(integration.providerIdentifier);\nconst tool = tools.find((t) => t.methodName === 'publishNow');\nif (!tool) throw new Error('Tool not available for this channel');\nawait triggerTool(integration.id, tool.methodName, {...});","handlingStrategy":"type-guard","validationCode":"const tools = await getProviderTools(integration.providerIdentifier);\nconst ok = tools.some((t) => t.methodName === body.methodName) && typeof (provider as any)?.[body.methodName] === 'function';\nif (!ok) throw new Error(`Tool ${body.methodName} not available on ${integration.providerIdentifier}`);","typeGuard":"const isToolCallable = (provider: object, name: string): name is string =>\n  name in provider && typeof (provider as any)[name] === 'function';","tryCatchPattern":"try {\n  await triggerTool(id, method, args);\n} catch (e: any) {\n  if (e?.status === 404 && e?.response?.msg === 'Tool not found') {\n    // fix methodName spelling/casing or pick a tool valid for this channel type\n  } else throw e;\n}","preventionTips":["Discover tool names from the provider metadata instead of hardcoding strings","Type methodName literals as a union derived from the provider's tool list","Validate the tool applies to the integration's channel type before invoking"],"tags":["public-api","tool-invocation","method-not-found","http-404"],"backgroundTag":"method-not-found","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}