babel/babel · error · Error
${msg(loc)} must be a undefined, a boolean, a string/Functio
Error message
${msg(loc)} must be a undefined, a boolean, a string/Function/RegExp or an array of those, got ${JSON.stringify(value as any)} What it means
Thrown by assertBabelrcSearch when 'babelrcRoots' is a single non-array value that is not undefined, boolean, string, Function, or RegExp. The offending value is JSON.stringified in the message.
Source
Thrown at packages/babel-core/src/config/validation/option-assertions.ts:326
export function assertBabelrcSearch(
loc: OptionPath,
value: unknown,
): BabelrcSearch | undefined {
if (value === undefined || typeof value === "boolean") {
return value;
}
if (Array.isArray(value)) {
value.forEach((item, i) => {
if (!checkValidTest(item)) {
throw new Error(
`${msg(access(loc, i))} must be a string/Function/RegExp.`,
);
}
});
} else if (!checkValidTest(value)) {
throw new Error(
`${msg(loc)} must be a undefined, a boolean, a string/Function/RegExp ` +
`or an array of those, got ${JSON.stringify(value as any)}`,
);
}
return value as BabelrcSearch;
}
export function assertPluginList(
loc: OptionPath,
value: unknown[] | null | undefined,
): PluginItem[] {
const arr = assertArray(loc, value);
if (arr) {
// Loop instead of using `.map` in order to preserve object identity
// for plugin array for use during config chain processing.
arr.forEach((item, i) => assertPluginItem(access(loc, i), item));
}
return arr as PluginItem[];View on GitHub (pinned to 06b6eae39d)
Solutions
- Pass true to enable all roots, false to disable, or a glob string/array of globs.
- Convert object wrappers to a flat array of path strings.
- Omit to use the default (babelrc disabled outside the root).
Example fix
// before
{ babelrcRoots: { roots: ['packages/*'] } }
// after
{ babelrcRoots: ['packages/*'] } Defensive patterns
Strategy: type-guard
Validate before calling
function isBabelrcSearch(v) {
if (v === undefined || typeof v === 'boolean') return true;
if (typeof v === 'string' || typeof v === 'function' || v instanceof RegExp) return true;
if (Array.isArray(v)) return v.every(isBabelrcSearch);
return false;
}
if (!isBabelrcSearch(opts.babelrcRoots)) {
throw new Error('babelrcRoots invalid');
} Type guard
function isBabelrcSearch(v: unknown): boolean {
if (v === undefined || typeof v === 'boolean') return true;
if (typeof v === 'string' || typeof v === 'function' || v instanceof RegExp) return true;
if (Array.isArray(v)) return v.every(isBabelrcSearch);
return false;
} Try / catch
try {
babel.loadOptions(opts);
} catch (e) {
if (e instanceof Error && /babelrcRoots must be/.test(e.message)) {
opts.babelrcRoots = true;
return babel.loadOptions(opts);
}
throw e;
} Prevention
- Prefer boolean or array-of-globs for babelrcRoots.
- Do not pass objects or numbers.
- For monorepos, use ['packages/*'] patterns.
When it happens
Trigger: babelrcRoots: { roots: ['a'] } (object); babelrcRoots: 42; babelrcRoots: null. The loc points at the option itself.
Common situations: Passing a config object expecting it to be merged; using a number expecting boolean semantics; legacy configs migrated from .babelrcrc roots.
Related errors
- You appear to be using an async configuration, which your cu
- Error while parsing config - ${err.message}
- No config detected
- Config returned typeof ${typeof options}
- Expected config object but found array
AI-assisted analysis of babel/babel@06b6eae39d (2026-08-03).
Data as JSON: /data/errors/d00944bf685ca44c.json.
Report an issue: GitHub.