Budibase/budibase · error · HTTPError

Link token is not valid for this workspace

Error message

Link token is not valid for this workspace

What it means

assertSessionMatchesInstance ensures the workspace (instance) encoded in the stored link-token session matches the :instance path parameter of the request. This prevents a token issued for one workspace/app from being redeemed against another. If workspaceId is missing or differs from the instance in the URL, a 400 is thrown.

Source

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

      }
`

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 =
    ctx.user?.globalId ||
    getGlobalIDFromUserMetadataID(ctx.user?._id || "") ||
    ctx.user?._id
  if (!currentUserId) {
    throw new HTTPError("Unable to resolve current user", 400)
  }
  return currentUserId
}

const providerDisplayName = (provider: ChatIdentityLinkProvider) => {
  if (provider === AgentChannelProvider.MSTEAMS) {
    return "Teams"
  }

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Open the link exactly as generated, matching the workspace it was issued for
  2. Regenerate the identity link from within the correct workspace
  3. If the app was recreated/migrated, re-issue the link so session.workspaceId matches the new instance id
  4. Fix link-generation code to embed the current workspace id in the instance path segment

Example fix

// before
// token issued in workspaceId=app_dev, but requesting:
fetch(`/api/chat-links/${otherInstanceId}/${token}/confirm`)
// after
fetch(`/api/chat-links/${workspaceId}/${token}/confirm`)
Defensive patterns

Strategy: validation

Validate before calling

if (session.workspaceId !== instanceId) throw new Error("link token belongs to a different workspace")

Type guard

function matchesInstance(session: { workspaceId?: string }, instance: string): session is { workspaceId: string } {
  return typeof session.workspaceId === "string" && session.workspaceId === instance
}

Try / catch

try {
  await api.confirmLink(instance, token)
} catch (e) {
  if (e instanceof HTTPError && e.status === 400 && e.message.includes("not valid for this workspace")) {
    // re-issue the link from the correct workspace
  }
  throw e
}

Prevention

When it happens

Trigger: Redeeming a handoff or confirm link where the instance segment in the URL does not equal session.workspaceId — e.g. swapping the workspace id in the URL, using a token generated in app A while browsing app B, or a session stored without a workspaceId.

Common situations: Multi-tenant environments where users belong to several apps and paste a link into the wrong app's domain/URL; environments migrated or renamed instances so stored workspaceId no longer matches; copying an old link after the app was recreated with a new id.

Related errors


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