Mintplex-Labs/anything-llm · error

Registration token is required

Error message

Registration token is required

What it means

validRegistrationToken guards POST /api/mobile/register. It reads the Authorization header and takes the second space-separated segment as the temporary token; if there is no Authorization header or no token segment, it responds 400 { error: 'Registration token is required' }.

Source

Thrown at server/endpoints/mobile/middleware/index.js:58

    response.status(500).json({ error: "Invalid middleware response" });
  }
}

/**
 * Validates a temporary registration token that is passed in the request
 * and associates the user with the token (if valid). Temporary token is consumed
 * and cannot be used again after this middleware is called.
 * @param {*} request
 * @param {*} response
 * @param {*} next
 */
async function validRegistrationToken(request, response, next) {
  try {
    const authHeader = request.header("Authorization");
    const tempToken = authHeader ? authHeader.split(" ")[1] : null;
    if (!tempToken)
      return response
        .status(400)
        .json({ error: "Registration token is required" });

    const tempTokenData = MobileDevice.tempToken(tempToken);
    if (!tempTokenData)
      return response
        .status(400)
        .json({ error: "Invalid or expired registration token" });

    // If in multi-user mode, we need to validate the user id
    // associated exists, is not banned and then associate with locals so we can reuse it later.
    // If not in multi-user mode then simply having a valid token is enough.
    const multiUserMode = await SystemSettings.isMultiUserMode();
    if (multiUserMode) {
      if (!tempTokenData.userId)
        return response
          .status(400)
          .json({ error: "User id not found in registration token" });
      const user = await User.get({ id: Number(tempTokenData.userId) });

View on GitHub (pinned to 3aec848f28)

Solutions

  1. Send 'Authorization: Bearer <tempToken>' where tempToken is the t query param of the connect-info URL/QR
  2. Keep the exact 'Bearer ' prefix with a single space
  3. Parse ?t= from the connection URL before issuing the register request

Example fix

// before
fetch('/api/mobile/register', {
  method: 'POST',
  headers: { 'x-registration-token': tempToken },
  body: JSON.stringify({ deviceOs: 'android', deviceName }),
});

// after
fetch('/api/mobile/register', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${tempToken}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ deviceOs: 'android', deviceName }),
});
Defensive patterns

Strategy: validation

Validate before calling

if (!tempToken) throw new Error('No registration token — fetch connect-info first');
const headers = { Authorization: `Bearer ${tempToken}` };

Prevention

When it happens

Trigger: POST /api/mobile/register with no Authorization header, with 'Bearer' but no token, with a raw token lacking the 'Bearer ' prefix (split(' ')[1] is undefined), or with a non-space-separated scheme.

Common situations: Client puts the temp token in a custom header or the JSON body instead of Authorization: Bearer <t>; the t= param from the connect-info URL was never extracted before calling register.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@3aec848f28 (2026-08-18). Data as JSON: /api/errors/ade9de9943197571. Report an issue: GitHub.