Budibase/budibase · error · HTTPError

agentId is required

Error message

agentId is required

What it means

prepareChatConversationForSave builds the ChatConversation document to persist. It resolves agentId from the existing chat or the incoming request; if neither provides one, the conversation cannot be associated with an agent and a 400 HTTPError is thrown. The field is required for every saved chat conversation.

Source

Thrown at packages/server/src/sdk/workspace/ai/chatConversations/helpers.ts:36

}

export const prepareChatConversationForSave = ({
  chatId,
  userId,
  title,
  messages,
  chat,
  existingChat,
}: PrepareChatConversationForSaveParams): ChatConversation => {
  const now = new Date().toISOString()
  const createdAt = existingChat?.createdAt || chat.createdAt || now
  const updatedAt = now
  const rev = existingChat?._rev || chat._rev
  const agentId = existingChat?.agentId || chat.agentId
  const channel = chat.channel || existingChat?.channel

  if (!agentId) {
    throw new HTTPError("agentId is required", 400)
  }

  return {
    _id: chatId,
    ...(rev && { _rev: rev }),
    agentId,
    userId,
    title: title ?? chat.title,
    messages: truncateToolPartsForSave(messages),
    updatedAt,
    ...(createdAt && { createdAt }),
    ...(channel && { channel }),
  }
}

export const extractUserText = (
  message?: ChatConversation["messages"][number]
) => {

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Include agentId in the ChatConversationRequest payload when creating/updating conversations.
  2. Verify the existing conversation document has agentId before attempting updates.
  3. Catch the 400 HTTPError and reject/repair requests missing agentId at the API boundary.

Example fix

// before
await api.saveChatConversation({ chatId, messages }) // 400: agentId required
// after
await api.saveChatConversation({ chatId, agentId: agent._id, messages })
Defensive patterns

Strategy: validation

Validate before calling

const canSave = (chat: Partial<ChatConversationRequest>, existing?: ChatConversation | null) =>
  !!(existing?.agentId || chat.agentId)
if (!canSave(chat, existingChat)) {
  throw new HTTPError("agentId is required", 400)
}

Type guard

const hasAgentId = (
  chat: Partial<ChatConversationRequest>,
  existingChat?: ChatConversation | null
): chat is Partial<ChatConversationRequest> & { agentId: string } =>
  !!(existingChat?.agentId || chat.agentId)

Try / catch

try {
  const doc = prepareChatConversationForSave(params)
} catch (err) {
  if (err instanceof HTTPError && err.status === 400 && err.message === "agentId is required") {
    // reject the request / repair the payload with the resolved agentId
  }
}

Prevention

When it happens

Trigger: Saving/creating a chat conversation where chat.agentId is missing and there is no existingChat to inherit it from - e.g. a client POSTing a conversation payload without agentId, or updating a conversation whose stored agentId was lost.

Common situations: Custom chat integrations omitting agentId in the request body; API version changes altering required fields; corrupted/existing conversations missing agentId being updated.

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/c381cfaf8c8f79bb. Report an issue: GitHub.