{"record":{"id":"ac5471529d5056b8","repo":"Budibase/budibase","slug":"cannot-manually-trigger-automation-automation-n","errorCode":null,"errorMessage":"Cannot manually trigger automation '${automation.name}'. Only automations with APP trigger type can be manually triggered. This automation has trigger type: ${triggerType}","messagePattern":"Cannot manually trigger automation '(.+?)'\\. Only automations with APP trigger type can be manually triggered\\. This automation has trigger type: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/sdk/workspace/automations/execution.ts","lineNumber":23,"sourceCode":"import * as triggers from \"../../../automations/triggers\"\nimport env from \"../../../environment\"\n\nexport async function trigger(\n  automationId: string,\n  fields: Record<string, any> = {},\n  timeout?: number\n) {\n  const db = context.getWorkspaceDB()\n  const automation = await db.get<Automation>(automationId)\n\n  if (!automation) {\n    throw new Error(`Automation with ID ${automationId} not found`)\n  }\n\n  // Check if automation has APP trigger (required for manual triggering)\n  const triggerType = automation.definition?.trigger?.stepId\n  if (triggerType !== \"APP\") {\n    throw new Error(\n      `Cannot manually trigger automation '${automation.name}'. Only automations with APP trigger type can be manually triggered. This automation has trigger type: ${triggerType}`\n    )\n  }\n\n  let hasCollectStep = sdk.automations.utils.checkForCollectStep(automation)\n  if (hasCollectStep && (await features.isSyncAutomationsEnabled())) {\n    const response = await triggers.externalTrigger(\n      automation,\n      {\n        fields,\n        timeout: timeout ? timeout * 1000 : env.AUTOMATION_THREAD_TIMEOUT,\n      },\n      { getResponses: true }\n    )\n\n    if (!(\"steps\" in response)) {\n      throw new Error(\"Unable to collect response\")\n    }","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/automations/execution.ts#L5-L41","documentation":"Thrown by `trigger` when the automation exists but its definition.trigger.stepId is not \"APP\". Only automations whose entry point is the Row/APP trigger can be triggered manually via this API; scheduled (CRON), webhook, or other trigger types are rejected with this message naming the actual trigger type found.","triggerScenarios":"Manually triggering (POST to the manual trigger endpoint or sdk.automations.execution.trigger) an automation whose trigger is CRON (schedule), WEBHOOK, or any non-APP stepId.","commonSituations":"Developers assume any automation can be run on demand from the API; a cron-driven automation is being tested via the manual endpoint; a webhook-triggered automation is invoked through the manual trigger route instead of its webhook URL.","solutions":["Open the automation in the builder and confirm its trigger is the \"Row Action / APP\" trigger type","For CRON automations, test by adjusting the schedule or temporarily switching the trigger to APP in a dev environment","For webhook automations, call the automation's dedicated webhook URL instead of the manual trigger endpoint","Duplicate the automation, set its trigger to APP, and trigger the duplicate if a manual run is required"],"exampleFix":"// before\nawait sdk.automations.execution.trigger(cronAutomationId) // throws\n// after\nconst automation = await db.get<Automation>(cronAutomationId)\nif (automation.definition?.trigger?.stepId !== \"APP\") {\n  // run via schedule or create an APP-triggered copy\n} else {\n  await sdk.automations.execution.trigger(cronAutomationId)\n}","handlingStrategy":"validation","validationCode":"const a = await db.get<Automation>(id)\nif (a.definition?.trigger?.stepId !== \"APP\") {\n  throw new Error(\"Manual trigger requires an APP trigger type\")\n}","typeGuard":"function isAppTriggered(a: Automation): boolean {\n  return a.definition?.trigger?.stepId === \"APP\"\n}","tryCatchPattern":"try {\n  await sdk.automations.execution.trigger(id)\n} catch (err: any) {\n  if (err.message.includes(\"APP trigger type\")) {\n    // use webhook URL or schedule instead\n  } else {\n    throw err\n  }\n}","preventionTips":["Check trigger stepId before manual triggering","Trigger webhooks via webhook URLs and CRON via schedule","Create APP-triggered copies for on-demand testing"],"tags":["automation","trigger-type","validation"],"backgroundTag":"invalid-operation-for-state","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}