RocketChat/Rocket.Chat · error · Meteor.Error

invalid-idle-time-limit-value

invalid-idle-time-limit-value

Error message

Invalid idleTimeLimit

What it means

Thrown by saveUserPreferences (DDP method behind POST /v1/users.setPreferences) when the submitted idleTimeLimit preference is present (not null/undefined) and is below 60. The value is in seconds and 60 is the enforced minimum so idle detection cannot flap sub-minute. Note the check only rejects the low bound - non-numeric values are caught earlier by argument checking.

Source

Thrown at apps/meteor/server/meteor-methods/users/saveUserPreferences.ts:210

	if (settings.language != null) {
		await Users.setLanguage(user._id, settings.language);
	}

	// utcOffset lives at the user-document root (not under settings.preferences)
	if (settings.utcOffset != null) {
		await Users.setUtcOffset(user._id, settings.utcOffset);
		delete settings.utcOffset;
	}

	// Keep compatibility with old values
	if (settings.emailNotificationMode === 'all') {
		settings.emailNotificationMode = 'mentions';
	} else if (settings.emailNotificationMode === 'disabled') {
		settings.emailNotificationMode = 'nothing';
	}

	if (settings.idleTimeLimit != null && settings.idleTimeLimit < 60) {
		throw new Meteor.Error('invalid-idle-time-limit-value', 'Invalid idleTimeLimit');
	}

	const requested = settings.statusVisibilityDenied?.filter((username) => username !== user.username);
	const denied = requested ? await resolveUsersByUsernames(requested) : undefined;

	if (denied) {
		settings.statusVisibilityDenied = denied.usernames;
	}

	await Users.setPreferences(user._id, denied ? { ...settings, statusVisibilityDenied: denied.ids } : settings);

	const diff = (Object.keys(settings) as (keyof UserPreferences)[]).reduce<Record<string, any>>((data, key) => {
		data[`settings.preferences.${key}`] = settings[key];

		return data;
	}, {});

	void notifyOnUserChange({

View on GitHub (pinned to b263243745)

Solutions

  1. Clamp the value before saving: idleTimeLimit = Math.max(60, value).
  2. Set min={60} (and step=60) on the form input and document the unit as seconds.
  3. Omit the key entirely to keep the current value instead of sending a small placeholder like 0.

Example fix

// before
await Meteor.callAsync('saveUserPreferences', { idleTimeLimit: seconds < 60 ? seconds : seconds }); // 30 -> throws

// after
const idleTimeLimit = Math.max(60, Math.round(seconds));
await Meteor.callAsync('saveUserPreferences', { idleTimeLimit });
Defensive patterns

Strategy: validation

Validate before calling

const MIN_IDLE = 60; // seconds, enforced server-side
if (prefs.idleTimeLimit != null && prefs.idleTimeLimit < MIN_IDLE) {
  prefs.idleTimeLimit = MIN_IDLE; // or reject with an inline form error
}
await Meteor.callAsync('saveUserPreferences', prefs);

Type guard

const isValidIdleTimeLimit = (v: unknown): v is number =>
  typeof v === 'number' && Number.isFinite(v) && v >= 60;

Try / catch

try {
  await Meteor.callAsync('saveUserPreferences', prefs);
} catch (e) {
  if ((e as Meteor.Error).error === 'invalid-idle-time-limit-value') {
    setInlineError('idleTimeLimit', 'Must be at least 60 seconds');
    await Meteor.callAsync('saveUserPreferences', { ...prefs, idleTimeLimit: 60 });
  }
}

Prevention

When it happens

Trigger: saveUserPreferences({ idleTimeLimit: 30 }); UI number inputs with min=0 allowing values under 60; units confusion - sending milliseconds (e.g. 30000 as '30s') is accepted but sending 30 meaning 30s is rejected.

Common situations: Preference forms without a lower bound; importing preferences from another system that stores idle minutes or milliseconds; tests using tiny values for fast idle.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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