{"record":{"id":"e8bd09886bd0fa85","repo":"Stirling-Tools/Stirling-PDF","slug":"tool-operation-not-supported-operationname","errorCode":null,"errorMessage":"Tool operation not supported: ${operationName}","messagePattern":"Tool operation not supported: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/core/utils/automationExecutor.ts","lineNumber":176,"sourceCode":"    files,\n    toolRegistry,\n    AUTOMATION_CONSTANTS.FILE_PREFIX,\n  );\n};\n\n/**\n * Execute a tool operation with custom prefix\n */\nexport const executeToolOperationWithPrefix = async (\n  operationName: string,\n  parameters: ErasedToolParams,\n  files: File[],\n  toolRegistry: ToolRegistry,\n  filePrefix: string = AUTOMATION_CONSTANTS.FILE_PREFIX,\n): Promise<File[]> => {\n  const config = toolRegistry[operationName as ToolId]?.operationConfig;\n  if (!config) {\n    throw new Error(`Tool operation not supported: ${operationName}`);\n  }\n\n  // Merge with default parameters to ensure all required fields are present\n  const mergedParameters = { ...config.defaultParameters, ...parameters };\n\n  try {\n    // Check if tool uses custom processor (like Convert tool)\n    if (config.customProcessor) {\n      const result = await config.customProcessor(mergedParameters, files);\n      return result.files;\n    }\n\n    // Execute based on tool type\n    if (config.toolType === ToolType.multiFile) {\n      return await executeMultiFileOperation(\n        config,\n        mergedParameters,\n        files,","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/utils/automationExecutor.ts#L158-L194","documentation":"Thrown by executeToolOperationWithPrefix when toolRegistry[operationName] has no operationConfig (or the ToolId key is absent entirely). Unlike errors 61/62 (tool exists but endpoint missing), here the tool is not registered for direct execution at all. The operationName is interpolated so the caller can see exactly which id failed.","triggerScenarios":"Calling executeToolOperationWithPrefix(op, params, files, registry) where op is not a key in registry, or is a key whose value lacks .operationConfig. This includes typos, stale ids from an imported automation JSON, or tool ids that are valid ToolIds but were stripped from a partial/custom registry.","commonSituations":"An imported automation JSON references a tool id that was renamed or removed in a newer build. The user hand-typed an operation name with a typo. A custom/partial ToolRegistry was passed that only contains a subset of tools. The operation id in the JSON is a display id, not the canonical ToolId.","solutions":["Log or surface the exact operationName from the error and check it against the keys of toolsTaxonomy (the ToolRegistry).","Correct the typo or update the automation JSON to use the current canonical tool id.","If the tool was removed, replace that step with an equivalent supported tool or remove the step.","Validate the automation JSON against the registry before execution — parseAutomationFile already collects unresolvedOperations for this purpose; surface those to the user first."],"exampleFix":"// before — JSON has \"operation\": \"splitt\" (typo)\n// after  — \"operation\": \"split\"","handlingStrategy":"validation","validationCode":"const KNOWN_OPS = new Set(Object.keys(toolRegistry).filter(id => toolRegistry[id]?.operationConfig));\n\nif (!KNOWN_OPS.has(operationName)) {\n  throw new Error(`Unknown operation '${operationName}'. Supported: ${[...KNOWN_OPS].join(', ')}`);\n}","typeGuard":"function isSupportedOperation(name: string, registry: ToolRegistry): boolean {\n  return !!(registry[name as ToolId]?.operationConfig);\n}","tryCatchPattern":"try {\n  await executeToolOperationWithPrefix(op, params, files, registry);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Tool operation not supported')) {\n    showUser(`Operation '${op}' is not available in this build.`);\n  } else { throw e; }\n}","preventionTips":["Validate imported automation operation ids against the registry at import time (use the unresolvedOperations list from parseAutomationFile).","Surface unresolved operations to the user before they attempt to run.","Keep a canonical list of operation ids and validate against it in the automation builder.","Add a regression test mapping example automations to supported operations."],"tags":["automation","tool-registry","validation","not-found"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}