Budibase/budibase · error · HTTPError

token is required

Error message

token is required

What it means

resolveToken is a small helper that guarantees a link token exists before any chat identity link flow proceeds. Identity linking works by handing a one-time token from a chat channel to the web app via URL; without a token there is nothing to resolve. The throw is an HTTP 400 guarding routes like /api/chat-links/:instance/:token/... .

Source

Thrown at packages/server/src/api/controllers/ai/chatIdentityLinks.ts:112

        outline: 2px solid #2680eb;
        outline-offset: 2px;
      }
      @media (max-width: 480px) {
        body {
          padding: 24px;
        }
        main {
          min-height: 360px;
        }
        h1 {
          font-size: 22px;
        }
      }
`

const resolveToken = (token?: string) => {
  if (!token) {
    throw new HTTPError("token is required", 400)
  }
  return token
}

const assertSessionMatchesInstance = ({
  workspaceId,
  instance,
}: {
  workspaceId?: string
  instance: string
}) => {
  if (!workspaceId || workspaceId !== instance) {
    throw new HTTPError("Link token is not valid for this workspace", 400)
  }
}

const getCurrentGlobalUserId = (ctx: UserCtx) => {
  const currentUserId =

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Use the exact handoff/confirmation URL supplied by the chat channel message, including the token segment
  2. Regenerate the link token by re-issuing the link request from the chat (e.g. typing the link command again)
  3. Fix link-rendering code so the token is interpolated into the URL template
  4. Check route definitions so the :token param is actually captured by the router

Example fix

// before
const res = await fetch(`/api/chat-links/${instance}/handoff`)
// after
const res = await fetch(`/api/chat-links/${instance}/${token}/handoff`)
Defensive patterns

Strategy: validation

Validate before calling

if (!token) throw new Error("chat link token missing from URL")
await fetch(`/api/chat-links/${instance}/${token}/handoff`)

Type guard

function hasToken(params: { token?: string }): params is { token: string } {
  return typeof params.token === "string" && params.token.length > 0
}

Try / catch

try {
  await api.handoffLink(instance, token)
} catch (e) {
  if (e instanceof HTTPError && e.status === 400 && e.message === "token is required") {
    // fix link construction / prompt user to use the full link
  }
  throw e
}

Prevention

When it happens

Trigger: Hitting a chat-links route (handoff or confirm) with an empty or missing :token path parameter, or calling resolveToken with undefined because the URL was constructed without the token segment.

Common situations: Manually typing/truncating the confirmation URL from an email/chat message; a chat bot rendering the link without the token placeholder substituted; links copied without the final path segment; redirect logic losing the token query/path param.

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