meteor/meteor · error · Error
options.on must be an array
Error message
options.on must be an array
What it means
Thrown by Meteor.deferrable when its options.on value is present but not an array. deferrable wraps a function so it runs in the background only in the listed environments (development/production/test); the on field must be an array of those string names. A non-array value is rejected before any environment comparison so the contract is explicit.
Source
Thrown at packages/meteor/timers.js:100
*/
Meteor.defer = function (f) {
Meteor._setImmediate(bindAndCatch("defer callback", f));
};
/**
* @memberOf Meteor
* @summary Wrap a function so that it only runs in background in specified environments..
* @locus Anywhere
* @param {Function} func The function to run
* @param {Object} options The options object
* @param {Array<String>} options.on Condition to determine whether to defer the function, you can pass an array of environments ['development', 'production', 'test']
*/
Meteor.deferrable = function (f, options) {
var on = (options && options.on) || [];
// throw if on is not an array
if (!Array.isArray(on)) {
throw new Error("options.on must be an array");
}
var env = Meteor.isDevelopment
? "development"
: Meteor.isProduction
? "production"
: "test";
if (on.includes(env)) {
return Meteor.defer(f);
}
return f();
};
/**
* @memberOf Meteor
* @summary Wrap a function to run in the background in development (similar to Meteor.isDevelopment ? Meteor.defer(fn) : Meteor.startup(fn)).View on GitHub (pinned to 5076d2f818)
Solutions
- Pass an array literal: Meteor.deferrable(fn, { on: ['production'] }).
- If the env list comes from config, normalize it first: `const on = Array.isArray(cfg.envs) ? cfg.envs : [cfg.envs]`.
- Prefer the convenience wrappers Meteor.deferDev and Meteor.deferProd when you only need a fixed environment.
- Omit options.on entirely if you never want deferred execution (the function then runs synchronously).
Example fix
// before
Meteor.deferrable(flushCache, { on: 'production' });
// after
Meteor.deferrable(flushCache, { on: ['production'] }); Defensive patterns
Strategy: type-guard
Validate before calling
function deferrableSafe(fn, options) {
const opts = options || {};
if (opts.on !== undefined && !Array.isArray(opts.on)) {
opts.on = Array.isArray(opts.on) ? opts.on : [opts.on];
}
return Meteor.deferrable(fn, opts);
} Type guard
function isValidOn(on) {
return on === undefined || Array.isArray(on);
} Prevention
- Always pass options.on as an array literal.
- Prefer Meteor.deferDev / Meteor.deferProd for fixed environments.
- Normalize config-derived env lists to arrays before calling deferrable.
When it happens
Trigger: Calling Meteor.deferrable(fn, { on: 'production' }) with a string instead of an array; passing { on: true } or { on: { env: 'production' } }; passing options.on as undefined is allowed (defaults to []), but any other non-array type throws.
Common situations: Migrating from Meteor.deferDev/Meteor.deferProd (which build the array internally) to Meteor.deferrable and forgetting the array literal; reading the env list from a config file as a string; copying example code that dropped the brackets.
Related errors
- ${allowOrDeny}: Invalid key: ${key}
- ${allowOrDeny}: Value for `${name}` must be a function
- ${allowOrDeny}: Value for `fetch` must be an array
- Can't set timers inside simulations
- Please specify only one of added() and addedAt()
AI-assisted analysis of meteor/meteor@5076d2f818 (2026-08-13).
Data as JSON: /api/errors/7325e82c78ad8ccb.
Report an issue: GitHub.