RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-field

error-invalid-field

Error message

bio

What it means

A runtime type guard on the bio field: saveUserProfile rejects settings.bio when it is present (truthy or empty string) but not a JS string (typeof settings.bio !== 'string'). No database write happens; the check runs before the length check and Users.setBio.

Source

Thrown at apps/meteor/server/meteor-methods/users/saveUserProfile.ts:91

			!(await saveUserIdentity({
				_id: this.userId,
				name: settings.realname,
				username: settings.username,
			}))
		) {
			throw new Meteor.Error('error-could-not-save-identity', 'Could not save user identity', {
				method: 'saveUserProfile',
			});
		}
	}

	if (settings.statusType || settings.statusText != null) {
		await setUserStatusMethod(user, settings.statusType as UserStatus, settings.statusText);
	}

	if (user && (settings.bio || settings.bio === '')) {
		if (typeof settings.bio !== 'string') {
			throw new Meteor.Error('error-invalid-field', 'bio', {
				method: 'saveUserProfile',
			});
		}
		if (settings.bio.length > MAX_BIO_LENGTH) {
			throw new Meteor.Error('error-bio-size-exceeded', `Bio size exceeds ${MAX_BIO_LENGTH} characters`, {
				method: 'saveUserProfile',
			});
		}
		await Users.setBio(user._id, settings.bio.trim());
	}

	if (user && (settings.nickname || settings.nickname === '')) {
		if (typeof settings.nickname !== 'string') {
			throw new Meteor.Error('error-invalid-field', 'nickname', {
				method: 'saveUserProfile',
			});
		}
		if (settings.nickname.length > MAX_NICKNAME_LENGTH) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Cast and validate on the client before calling: ensure typeof bio === 'string'
  2. Type the settings payload (bio?: string) in TS clients so the compiler blocks non-string values
  3. Inspect the actual DDP wire payload if a stock client triggers it - some serializer upstream is corrupting the value

Example fix

// before
Meteor.call('saveUserProfile', { bio: bioInput.valueAsNumber }, customFields);

// after
Meteor.call('saveUserProfile', { bio: String(bioInput.value) }, customFields);
Defensive patterns

Strategy: type-guard

Validate before calling

if ('bio' in settings && typeof settings.bio !== 'string') {
  throw new TypeError('bio must be a string');
}

Type guard

const isOptionalString = (v: unknown): v is string | undefined => v === undefined || typeof v === 'string';

Try / catch

catch (err) {
  if (err instanceof Meteor.Error && err.error === 'error-invalid-field' && err.reason === 'bio') {
    showFieldError('bio', 'Bio must be text');
  }
}

Prevention

When it happens

Trigger: Calling saveUserProfile with bio as a number, object, or array - e.g. bio: 123, bio: { text: '...' } - typically from a custom client, integration, or a form binding that did not cast the input value.

Common situations: Number-input form fields bound without String(); bots/integrations posting untyped JSON; REST-to-DDP bridges that pass raw JSON values through.

Related errors


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