RocketChat/Rocket.Chat · error · Meteor.Error

error-parameter-required

error-parameter-required

Error message

x-auth-token is required

What it means

Thrown by POST /api/v1/users.removeOtherSessions when the x-auth-token request header is absent. The endpoint keeps only the session that owns the supplied token and invalidates every other non-PAT login token, so without the header it cannot know which session to preserve and fails with error-parameter-required.

Solutions

  1. Send the current session's auth token in the x-auth-token header exactly as returned by the login endpoint
  2. Fix proxy/gateway configuration to forward x-auth-token
  3. Use the official REST SDK which forwards the header automatically
  4. Retry only after confirming the header arrives (log sanitized request headers server-side)

Example fix

// before
await fetch('/api/v1/users.removeOtherSessions', { method: 'POST', headers: { 'X-Auth-Token': token, 'X-User-Id': uid } }); // proxy strips header
// after
await fetch('/api/v1/users.removeOtherSessions', { method: 'POST', headers: { 'x-auth-token': token, 'x-user-id': uid } });
Defensive patterns

Strategy: validation

Validate before calling

if (!headers['x-auth-token']) throw new Error('x-auth-token header required for users.removeOtherSessions');
await sdk.post('users.removeOtherSessions', {}, { 'x-auth-token': authToken });

Type guard

const hasXAuthToken = (h: Record<string,string|undefined>): h is {'x-auth-token': string} => Boolean(h['x-auth-token']);

Try / catch

try { await sdk.post('users.removeOtherSessions', {}, headers); } catch (e) { if (e.response?.data?.errorType === 'error-parameter-required') { ensureHeaderForwarding(); } else throw e; }

Prevention

When it happens

Trigger: POST users.removeOtherSessions with only the standard auth headers of a wrapper SDK that strips x-auth-token; sending X-Auth-Token with different casing handled upstream but the header dropped by a proxy; calling with a userId param but no token header.

Common situations: Custom fetch wrappers that whitelist Content-Type/X-Auth-Token inconsistently; reverse proxies or API gateways stripping x-auth-token; SDK versions that send the token in a different header name.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@e4b8178b20 (2026-08-18). Data as JSON: /api/errors/d4e7b4cb7e4c21fe. Report an issue: GitHub.

Appendix: source

Thrown at apps/meteor/server/api/v1/users.ts:1676

			response: {
				200: ajv.compile<{ token: string; tokenExpires: string }>({
					type: 'object',
					properties: {
						token: { type: 'string' },
						tokenExpires: { type: 'string' },
						success: { type: 'boolean', enum: [true] },
					},
					required: ['token', 'tokenExpires', 'success'],
					additionalProperties: false,
				}),
				401: validateUnauthorizedErrorResponse,
			},
		},
		async function action() {
			const xAuthToken = this.request.headers.get('x-auth-token') as string;

			if (!xAuthToken) {
				throw new Meteor.Error('error-parameter-required', 'x-auth-token is required');
			}
			const hashedToken = Accounts._hashLoginToken(xAuthToken);

			if (!(await Users.removeNonPATLoginTokensExcept(this.userId, hashedToken))) {
				throw new Meteor.Error('error-invalid-user-id', 'Invalid user id');
			}

			const me = (await Users.findOneById(this.userId, { projection: { 'services.resume.loginTokens': 1 } })) as Pick<IUser, 'services'>;

			void notifyOnUserChange({
				clientAction: 'updated',
				id: this.userId,
				diff: { 'services.resume.loginTokens': me.services?.resume?.loginTokens },
			});

			const token = me.services?.resume?.loginTokens?.find((token) => token.hashedToken === hashedToken);

			const loginExp = settings.get<number>('Accounts_LoginExpiration');

View on GitHub (pinned to e4b8178b20)