Budibase/budibase · error · HTTPError

agentId is required

Error message

agentId is required

What it means

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.

Source

Thrown at packages/server/src/sdk/workspace/ai/agents/crud.ts:447

  if (incoming.clientSecret === SECRET_MASK && existing?.clientSecret) {
    resolved.clientSecret = existing.clientSecret
  }

  if (incoming.signingSecret === SECRET_MASK && existing?.signingSecret) {
    resolved.signingSecret = existing.signingSecret
  }

  return resolved
}

export async function fetch(): Promise<Agent[]> {
  const agents = (await fetchRaw()).map(withAgentDefaults)
  return withCurrentQueryToolReferences(agents)
}

export async function getOrThrow(agentId: string | undefined): Promise<Agent> {
  if (!agentId) {
    throw new HTTPError("agentId is required", 400)
  }

  const db = context.getWorkspaceDB()
  const rawAgent = await db.tryGet<DeprecatedAgent>(agentId)
  if (!rawAgent) {
    throw new HTTPError("Agent not found", 404)
  }

  const agent = withAgentDefaults(rawAgent)
  const [resolvedAgent] = await withCurrentQueryToolReferences([agent])
  return resolvedAgent
}

export async function create(
  request: Optional<
    Omit<Agent, "_id" | "_rev" | "createdAt" | "updatedAt" | "publishedAt">,
    "aiconfig"
  >

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Ensure the caller supplies a real agent id — check where agentId originates (route params, stored config) for undefined/empty values
  2. For unsaved documents, persist or fetch the agent first so _id exists
  3. Guard the call: only invoke sdk.ai.agents.getOrThrow after verifying the id is a non-empty string
  4. Check the HTTP route/params wiring if agentId comes from a URL

Example fix

// before
const agent = await sdk.ai.agents.getOrThrow(config.agentId)
// after
if (!config.agentId) {
  throw new Error("No agent configured for this session")
}
const agent = await sdk.ai.agents.getOrThrow(config.agentId)
Defensive patterns

Strategy: validation

Validate before calling

if (!agentId || typeof agentId !== "string") {
  throw new Error("No agentId available")
}
const agent = await sdk.ai.agents.getOrThrow(agentId)

Type guard

function hasAgentId(v: { agentId?: string }): v is { agentId: string } {
  return typeof v.agentId === "string" && v.agentId.length > 0
}

Try / catch

try {
  agent = await sdk.ai.agents.getOrThrow(agentId)
} catch (err) {
  if (err instanceof HTTPError && err.status === 400) {
    // agentId was undefined/empty - fix the caller/config
  } else { throw err }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/c2f282cfa9b0dc30. Report an issue: GitHub.