{"record":{"id":"bc31e80e54fe9c66","repo":"Budibase/budibase","slug":"at-least-one-operation-field-is-required","errorCode":null,"errorMessage":"At least one operation field is required","messagePattern":"At least one operation field is required","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/ai/agentOperations.ts","lineNumber":47,"sourceCode":"    escalation: body.escalation,\n  })\n\n  ctx.body = toAgentResponse(agent)\n  ctx.status = 201\n}\n\nexport async function updateAgentOperation(\n  ctx: UserCtx<\n    UpdateAgentOperationRequest,\n    AgentOperationMutationResponse,\n    { agentId: string; operationId: string }\n  >\n) {\n  const { agentId, operationId } = ctx.params\n  const body = ctx.request.body\n\n  if (!Object.keys(body).length) {\n    throw new HTTPError(\"At least one operation field is required\", 400)\n  }\n\n  const agent = await sdk.ai.agents.updateOperation(agentId, operationId, body)\n\n  ctx.body = toAgentResponse(agent)\n  ctx.status = 200\n}\n\nexport async function deleteAgentOperation(\n  ctx: UserCtx<\n    void,\n    AgentOperationMutationResponse,\n    { agentId: string; operationId: string }\n  >\n) {\n  const { agentId, operationId } = ctx.params\n\n  const agent = await sdk.ai.agents.removeOperation(agentId, operationId)","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/ai/agentOperations.ts#L29-L65","documentation":"This error is thrown when updating an agent operation with an empty request body. The controller requires at least one field to modify; an empty JSON object ({}) gives the underlying sdk.ai.agents.updateOperation nothing to do, so it is rejected with 400.","triggerScenarios":"Sending PUT/PATCH to the agent operation endpoint with body {} , an empty form body, or a Content-Type/body mismatch that results in ctx.request.body being an empty object. The check is Object.keys(body).length === 0.","commonSituations":"HTTP clients sending PATCH with no body; middleware stripping the body due to missing Content-Type: application/json; code paths that build the update payload conditionally and end up with no fields; proxy or serialization dropping empty objects.","solutions":["Include at least one operation field in the JSON body","Ensure the request sets Content-Type: application/json and the body is actually parsed","Fix client logic that conditionally builds the payload so it never sends an empty object","If no changes are needed, skip the API call entirely instead of issuing an empty update"],"exampleFix":"// before\nawait api.patch(`/ai/agents/${agentId}/operations/${opId}`, {})\n// after\nawait api.patch(`/ai/agents/${agentId}/operations/${opId}`, { enabled: false })","handlingStrategy":"validation","validationCode":"function assertNonEmptyUpdate(body) {\n  if (!body || typeof body !== \"object\" || Object.keys(body).length === 0) {\n    throw new Error(\"update requires at least one operation field\")\n  }\n  return body\n}\nassertNonEmptyUpdate(payload)","typeGuard":"function hasUpdateFields(b) {\n  return typeof b === \"object\" && b !== null && Object.keys(b).length > 0\n}","tryCatchPattern":"try {\n  await updateAgentOperation(agentId, operationId, payload)\n} catch (err) {\n  if (err.status === 400 && err.message === \"At least one operation field is required\") {\n    console.warn(\"skipped empty update\")\n    return\n  }\n  throw err\n}","preventionTips":["Skip the API call when the diff of changes is empty","Always send Content-Type: application/json with PATCH/PUT bodies","Build update payloads from an explicit diff so they are never empty by accident","Log the outgoing body in dev to catch middleware stripping it"],"tags":["validation","http-400","empty-body","patch"],"backgroundTag":"empty-request-body","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}