{"record":{"id":"a535a58d95b228c4","repo":"Budibase/budibase","slug":"operation-not-found-for-this-agent-a535a5","errorCode":null,"errorMessage":"Operation not found for this agent","messagePattern":"Operation not found for this agent","errorType":"http","errorClass":"HTTPError","httpStatus":404,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/agents/operations.ts","lineNumber":27,"sourceCode":"  | \"promptInstructions\"\n  | \"enabledTools\"\n  | \"approvalPolicies\"\n  | \"allowKnowledgeSourceDownload\"\n  | \"escalation\"\n>\n\nexport type CreateAgentOperationInput = AgentOperationConfig &\n  Pick<AgentOperation, \"id\">\n\nconst normalizeOperationName = (name: string | undefined) =>\n  name?.trim().toLowerCase() || \"\"\n\nconst getOperationOrThrow = (agent: Agent, operationId: string) => {\n  const operation = agent.operations?.find(\n    candidate => candidate.id === operationId\n  )\n  if (!operation) {\n    throw new HTTPError(\"Operation not found for this agent\", 404)\n  }\n  return operation\n}\n\nconst mergeOperationConfig = (\n  existing: AgentOperation,\n  incoming: Partial<AgentOperationConfig>\n): AgentOperation => ({\n  ...existing,\n  ...incoming,\n  id: existing.id,\n  knowledgeBases: existing.knowledgeBases,\n  knowledgeSources: existing.knowledgeSources,\n  escalation: incoming.escalation ?? existing.escalation,\n})\n\nconst assertUniqueOperationName = (\n  agent: Agent,","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/agents/operations.ts#L9-L45","documentation":"getOperationOrThrow looks up an agent operation by ID within an agent's operations array. If no operation on the agent matches the given operationId, it throws a 404 HTTPError. This guards updateOperation and removeOperation against mutating a non-existent operation.","triggerScenarios":"Calling updateOperation(agentId, operationId, ...) or removeOperation(agentId, operationId) with an operationId that does not exist on the agent (deleted already, wrong agent, typo'd/stale ID from a client).","commonSituations":"Client UI holding a stale operation ID after the operation was removed; calling with an ID from a different agent; concurrent edits where one session deletes the operation another is editing.","solutions":["Fetch the agent and confirm the operationId exists in agent.operations before calling update/remove.","Refresh the agent document to get current operation IDs if the client may hold stale data.","Handle the 404 HTTPError in the API layer and surface 'operation not found' to the caller."],"exampleFix":"// before\nawait updateOperation(agentId, someStaleId, config) // 404\n// after\nconst agent = await getOrThrow(agentId)\nif (!agent.operations?.some(o => o.id === someStaleId)) {\n  throw new HTTPError(\"Operation not found for this agent\", 404)\n}\nawait updateOperation(agentId, someStaleId, config)","handlingStrategy":"type-guard","validationCode":"const op = agent.operations?.find(o => o.id === operationId)\nif (!op) throw new HTTPError(\"Operation not found\", 404)\n// only then call updateOperation/removeOperation","typeGuard":"const hasOperation = (agent: Agent, operationId: string): boolean =>\n  !!agent.operations?.some(o => o.id === operationId)","tryCatchPattern":"try {\n  await removeOperation(agentId, operationId)\n} catch (err) {\n  if (err instanceof HTTPError && err.status === 404) {\n    // treat as already-deleted / stale client data\n  }\n}","preventionTips":["Re-fetch the agent before mutating instead of trusting cached operation IDs.","Treat 404 on operation updates as idempotent-delete in clients.","Refresh UI state after any delete to avoid stale IDs."],"tags":["http-404","agents","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}