{"record":{"id":"c2f282cfa9b0dc30","repo":"Budibase/budibase","slug":"agentid-is-required-c2f282","errorCode":null,"errorMessage":"agentId is required","messagePattern":"agentId is required","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/sdk/workspace/ai/agents/crud.ts","lineNumber":447,"sourceCode":"  if (incoming.clientSecret === SECRET_MASK && existing?.clientSecret) {\n    resolved.clientSecret = existing.clientSecret\n  }\n\n  if (incoming.signingSecret === SECRET_MASK && existing?.signingSecret) {\n    resolved.signingSecret = existing.signingSecret\n  }\n\n  return resolved\n}\n\nexport async function fetch(): Promise<Agent[]> {\n  const agents = (await fetchRaw()).map(withAgentDefaults)\n  return withCurrentQueryToolReferences(agents)\n}\n\nexport async function getOrThrow(agentId: string | undefined): Promise<Agent> {\n  if (!agentId) {\n    throw new HTTPError(\"agentId is required\", 400)\n  }\n\n  const db = context.getWorkspaceDB()\n  const rawAgent = await db.tryGet<DeprecatedAgent>(agentId)\n  if (!rawAgent) {\n    throw new HTTPError(\"Agent not found\", 404)\n  }\n\n  const agent = withAgentDefaults(rawAgent)\n  const [resolvedAgent] = await withCurrentQueryToolReferences([agent])\n  return resolvedAgent\n}\n\nexport async function create(\n  request: Optional<\n    Omit<Agent, \"_id\" | \"_rev\" | \"createdAt\" | \"updatedAt\" | \"publishedAt\">,\n    \"aiconfig\"\n  >","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/sdk/workspace/ai/agents/crud.ts#L429-L465","documentation":"getOrThrow is the canonical agent lookup: it requires an agentId argument and throws a 400 HTTPError if it is undefined/empty, before even hitting the database. Callers throughout the SDK (agent, getAgentId, existing, sourceAgent, syncState, existingAgent) rely on this precondition.","triggerScenarios":"Calling getOrThrow(undefined) or getOrThrow(\"\") — typically from sdk.ai.agents.agent(undefined), a request where the :agentId param is missing, an object whose id field was never set, or destructuring an agent doc that lacks _id.","commonSituations":"API route invoked with a malformed/missing id segment; code reading agentId off a config or record that was never populated; passing the wrong property name (e.g. agent._id vs agent.id) resulting in undefined; freshly created (unsaved) objects that have no _id yet.","solutions":["Ensure the caller supplies a real agent id — check where agentId originates (route params, stored config) for undefined/empty values","For unsaved documents, persist or fetch the agent first so _id exists","Guard the call: only invoke sdk.ai.agents.getOrThrow after verifying the id is a non-empty string","Check the HTTP route/params wiring if agentId comes from a URL"],"exampleFix":"// before\nconst agent = await sdk.ai.agents.getOrThrow(config.agentId)\n// after\nif (!config.agentId) {\n  throw new Error(\"No agent configured for this session\")\n}\nconst agent = await sdk.ai.agents.getOrThrow(config.agentId)","handlingStrategy":"validation","validationCode":"if (!agentId || typeof agentId !== \"string\") {\n  throw new Error(\"No agentId available\")\n}\nconst agent = await sdk.ai.agents.getOrThrow(agentId)","typeGuard":"function hasAgentId(v: { agentId?: string }): v is { agentId: string } {\n  return typeof v.agentId === \"string\" && v.agentId.length > 0\n}","tryCatchPattern":"try {\n  agent = await sdk.ai.agents.getOrThrow(agentId)\n} catch (err) {\n  if (err instanceof HTTPError && err.status === 400) {\n    // agentId was undefined/empty - fix the caller/config\n  } else { throw err }\n}","preventionTips":["Check where agentId originates (route params, stored config) for undefined/empty","Use saved documents (with _id) rather than in-memory literals","Validate URL param presence before invoking SDK lookups"],"tags":["validation","http-400","crud"],"backgroundTag":"missing-required-field","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}