makeplane/plane · critical · AppError

AUTH_MISSING_CREDENTIALS

AUTH_MISSING_CREDENTIALS

Error message

Credentials not provided

What it means

In the Live (Hocuspocus) WebSocket authentication hook, after attempting to read a cookie from request parameters and falling back to request headers, the code requires both a cookie and a userId. If neither resolves, it raises an AppError with code AUTH_MISSING_CREDENTIALS and aborts the connection. This is the gatekeeper for the collaborative editing socket.

Solutions

  1. Ensure the browser has an authenticated session cookie before opening the Live socket (log in first).
  2. If behind a proxy, verify the Cookie header is forwarded to the WS handshake.
  3. Check logs for the preceding 'Token parsing failed' warning — a present cookie with empty userId usually means token decode failed.
  4. Confirm SameSite/Secure cookie attributes allow the WS origin.

Example fix

// before
new HocuspocusProvider({ url, name: docName });

// after
if (!document.cookie.includes('session')) {
  await redirectToLogin();
}
new HocuspocusProvider({ url, name: docName });
Defensive patterns

Strategy: validation

Validate before calling

function hasSessionCookie(): boolean { return /session/i.test(document.cookie); }
if (!hasSessionCookie()) { await redirectToLogin(); }

Try / catch

// at the WS provider onError/onAuthenticationFailed
provider.on('authenticationFailed', () => { redirectToLogin(); });

Prevention

When it happens

Trigger: Connecting to the Live WS endpoint without a session cookie (anonymous), with an expired/invalid session that yields no userId, or from a client that sends neither cookie param nor Cookie header.

Common situations: Cookie blocked by SameSite/Secure cross-origin; dev environment without a logged-in session; proxy stripping the Cookie header; token parsing silently failed so userId is empty even though a cookie was present.

Related errors


AI-assisted analysis of makeplane/plane@1c8a60f858 (2026-08-12). Data as JSON: /api/errors/2cb7f3f09b385b53. Report an issue: GitHub.

Appendix: source

Thrown at apps/live/src/lib/auth.ts:57

  // the cookies are not passed in the request headers)
  try {
    const parsedToken = JSON.parse(token) as TUserDetails;
    userId = parsedToken.id;
    cookie = parsedToken.cookie;
  } catch (error) {
    const appError = new AppError(error, {
      context: { operation: "onAuthenticate" },
    });
    logger.error("Token parsing failed, using request headers", appError);
  } finally {
    // If cookie is still not found, fallback to request headers
    if (!cookie) {
      cookie = requestHeaders.cookie?.toString();
    }
  }

  if (!cookie || !userId) {
    const appError = new AppError("Credentials not provided", { code: "AUTH_MISSING_CREDENTIALS" });
    logger.error("Credentials not provided", appError);
    throw appError;
  }

  // set cookie in context, so it can be used throughout the ws connection
  context.cookie = cookie ?? requestParameters.get("cookie") ?? "";
  context.documentType = requestParameters.get("documentType")?.toString() as TDocumentTypes;
  context.projectId = requestParameters.get("projectId");
  context.userId = userId;
  context.workspaceSlug = requestParameters.get("workspaceSlug");

  return await handleAuthentication({
    cookie: context.cookie,
    userId: context.userId,
  });
};

export const handleAuthentication = async ({ cookie, userId }: { cookie: string; userId: string }) => {

View on GitHub (pinned to 1c8a60f858)