Budibase/budibase · error · HTTPError

userId is required

Error message

userId is required

What it means

getGlobalUserId derives the caller's id from ctx.user (globalId || userId || _id). If the authenticated context carries no user or none of those fields, the endpoint cannot attribute the chat conversation and throws HTTP 400 'userId is required'.

Source

Thrown at packages/server/src/api/controllers/ai/chatConversations.ts:48

import sdk from "../../../sdk"
import { isDevWorkspaceID } from "../../../db/utils"
import {
  buildAgentMessageUsage,
  formatIncompleteToolCallError,
  prepareAgentChatRun,
  type AgentChatRun,
} from "../../../sdk/workspace/ai/agents"
import { sdk as usersSdk } from "@budibase/shared-core"
import { truncateTitle } from "../../../sdk/workspace/ai/chatConversations"
import {
  determineTrigger,
  resolvePreviewSessionId,
} from "../../../sdk/workspace/ai/agentLogs/shared"

const getGlobalUserId = (ctx: UserCtx) => {
  const userId = ctx.user?.globalId || ctx.user?.userId || ctx.user?._id
  if (!userId) {
    throw new HTTPError("userId is required", 400)
  }
  return userId as string
}

const getRecentChatContext = (
  messages: ChatConversation["messages"],
  limit = 6
) => {
  return messages
    .flatMap(message => {
      if (message.role !== "user" && message.role !== "assistant") {
        return []
      }

      const content = (message.parts || [])
        .filter(
          (
            part

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Ensure the request carries a valid authenticated user session/JWT
  2. Check ctx.user population in auth middleware — globalId should be present for SSO/JWT users
  3. For service-to-service calls, pass an explicit userId or use a user-scoped API key

Example fix

// before
fetch('/api/ai/chatconversations/recent') // no auth header
// after
fetch('/api/ai/chatconversations/recent', {
  headers: { Authorization: `Bearer ${token}` }
})
Defensive patterns

Strategy: validation

Validate before calling

if (!user || !(user.globalId || user.userId || user._id)) {
  throw new Error("Authenticated user with an id is required")
}

Type guard

const hasUserId = (u: unknown): u is { globalId: string } =>
  !!u && typeof u === "object" &&
  typeof (u as any).globalId === "string" && (u as any).globalId !== ""

Try / catch

try {
  await api.getRecentConversations()
} catch (e) {
  if (e.status === 400 && String(e.message).includes("userId is required")) {
    // re-authenticate the user session before retrying
  }
}

Prevention

When it happens

Trigger: Calling chat conversation endpoints (e.g. recent conversations) with an unauthenticated or malformed session token so ctx.user has no globalId/userId/_id.

Common situations: Expired or invalid JWT still passing middleware but with a stripped payload; internal service calls without user context; API keys used where a user session is expected.

Related errors


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