{"record":{"id":"c1c19b60b18986c2","repo":"Budibase/budibase","slug":"unable-to-resolve-current-user","errorCode":null,"errorMessage":"Unable to resolve current user","messagePattern":"Unable to resolve current user","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/ai/chatIdentityLinks.ts","lineNumber":135,"sourceCode":"const assertSessionMatchesInstance = ({\n  workspaceId,\n  instance,\n}: {\n  workspaceId?: string\n  instance: string\n}) => {\n  if (!workspaceId || workspaceId !== instance) {\n    throw new HTTPError(\"Link token is not valid for this workspace\", 400)\n  }\n}\n\nconst getCurrentGlobalUserId = (ctx: UserCtx) => {\n  const currentUserId =\n    ctx.user?.globalId ||\n    getGlobalIDFromUserMetadataID(ctx.user?._id || \"\") ||\n    ctx.user?._id\n  if (!currentUserId) {\n    throw new HTTPError(\"Unable to resolve current user\", 400)\n  }\n  return currentUserId\n}\n\nconst providerDisplayName = (provider: ChatIdentityLinkProvider) => {\n  if (provider === AgentChannelProvider.MSTEAMS) {\n    return \"Teams\"\n  }\n  if (provider === AgentChannelProvider.SLACK) {\n    return \"Slack\"\n  }\n\n  throw provider satisfies never\n}\n\nconst renderLinkConfirmationPage = (\n  session: ChatIdentityLinkSession,\n  action: string","sourceCodeStart":117,"sourceCodeEnd":153,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/ai/chatIdentityLinks.ts#L117-L153","documentation":"getCurrentGlobalUserId derives the caller's global user id from the authenticated context, trying ctx.user.globalId, then converting the metadata _id via getGlobalIDFromUserMetadataID, then falling back to _id. If none yields an id, the request context is not carrying a usable authenticated user, so a 400 is thrown.","triggerScenarios":"Calling an endpoint that invokes currentGlobalUserId (e.g. identity link handoff/confirm) with a ctx.user that is empty or lacks both globalId and _id — typically an unauthenticated or improperly populated auth context reaching an authenticated route.","commonSituations":"Auth middleware bypassed or misordered so ctx.user is never hydrated; internal/service calls invoking controller helpers without a real user context; user metadata documents missing ids after a sync/import issue; testing endpoints without a valid session/cookie or API key.","solutions":["Ensure the route is authenticated and the auth middleware populates ctx.user before the handler runs","Log in again or supply valid credentials (session cookie / API token) so ctx.user contains an id","Check the user document for missing _id/globalId and repair via user sync","If calling internally, pass a properly shaped ContextUser with at least _id"],"exampleFix":"// before\nawait confirmLink(ctx) // ctx.user undefined -> 400\n// after\n// ensure auth middleware ran\nrouter.post(\"/confirm\", authMiddleware, confirmLink) // ctx.user populated","handlingStrategy":"validation","validationCode":"const userId = ctx.user?.globalId || ctx.user?._id\nif (!userId) throw new Error(\"no authenticated user in context\")","typeGuard":"function hasResolvedUser(user?: ContextUser): user is ContextUser & { _id: string } {\n  return !!user && typeof user._id === \"string\" && user._id.length > 0\n}","tryCatchPattern":"try {\n  await api.confirmLink(instance, token)\n} catch (e) {\n  if (e instanceof HTTPError && e.status === 400 && e.message === \"Unable to resolve current user\") {\n    // redirect to login / re-run auth middleware\n  }\n  throw e\n}","preventionTips":["Ensure auth middleware runs before routes that need the current user","Never call these controller helpers without a hydrated ContextUser","Monitor user sync so _id/globalId are always present","Add route-level guards rejecting unauthenticated requests early"],"tags":["auth","user-context","http-400"],"backgroundTag":"unauthenticated-request","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}