{"record":{"id":"b12661867453d489","repo":"Stirling-Tools/Stirling-PDF","slug":"invalid-automation-config-operations-index-op","errorCode":null,"errorMessage":"Invalid automation config: operations[${index}].operation must be a non-empty string","messagePattern":"Invalid automation config: operations\\[(.+?)\\]\\.operation must be a non-empty string","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"frontend/editor/src/core/utils/automationConverter.ts","lineNumber":336,"sourceCode":"  }\n  const obj = raw as Record<string, unknown>;\n  const operations = obj.operations;\n  if (!Array.isArray(operations)) {\n    throw new Error(\"Invalid automation config: missing 'operations' array\");\n  }\n\n  const unresolved: string[] = [];\n  const parsedOperations: AutomationOperation[] = operations.map(\n    (op: unknown, index: number) => {\n      if (!op || typeof op !== \"object\") {\n        throw new Error(\n          `Invalid automation config: operations[${index}] is not an object`,\n        );\n      }\n      const opObj = op as Record<string, unknown>;\n      const operation = opObj.operation;\n      if (typeof operation !== \"string\" || operation.length === 0) {\n        throw new Error(\n          `Invalid automation config: operations[${index}].operation must be a non-empty string`,\n        );\n      }\n      const parameters = (opObj.parameters as Record<string, any>) || {};\n      if (!isToolIdInRegistry(operation, toolRegistry)) {\n        unresolved.push(operation);\n      }\n      return { operation, parameters };\n    },\n  );\n\n  const name =\n    typeof obj.name === \"string\" && obj.name.length > 0\n      ? obj.name\n      : \"Imported Automation\";\n\n  return {\n    automation: {","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/utils/automationConverter.ts#L318-L354","documentation":"Thrown when an operation entry's operation field is missing, not a string, or empty. It must be a non-empty frontend tool id present in the tool registry.","triggerScenarios":"op.operation is undefined, null, a number, or an empty string.","commonSituations":"A typo; an incomplete entry; an export referencing a tool id that was removed or renamed.","solutions":["Ensure each entry has a non-empty string operation matching a known tool id.","Re-export the config.","Validate against the current tool registry before running."],"exampleFix":"// before\nif (typeof operation !== 'string' || operation.length === 0) throw new Error('operation must be a non-empty string');\n\n// after\nconst known = new Set(Object.keys(toolRegistry));\nconst bad = operations.findIndex((o) => typeof (o as any)?.operation !== 'string' || !known.has((o as any).operation));\nif (bad !== -1) throw new Error(`operations[${bad}].operation is missing or unknown.`);","handlingStrategy":"validation","validationCode":"const known = new Set(Object.keys(toolRegistry));\nconst ok = operations.every((o) => typeof (o as any)?.operation === 'string' && known.has((o as any).operation));\nif (!ok) throw new Error('Each operation must be a known tool id.');","typeGuard":"function entryHasKnownOperation(o: unknown, registry: Partial<ToolRegistry>): boolean {\n  const op = (o as any)?.operation;\n  return typeof op === 'string' && op.length > 0 && Object.prototype.hasOwnProperty.call(registry, op);\n}","tryCatchPattern":null,"preventionTips":["Validate operation ids against the live tool registry before persisting/running.","Surface unresolvedOperations to the user so renamed/removed tools are visible."],"tags":["automation","config","validation","json"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}