rolldown/rolldown · error · TypeError
MagicString.prototype.replaceAll called with a non-global…
Error message
MagicString.prototype.replaceAll called with a non-global RegExp argument
What it means
binding-magic-string.ts implements replaceAll to match the JS magic-string/String.prototype.replaceAll spec: a RegExp argument must have the global (g) flag. If a non-global RegExp is passed, it throws this TypeError instead of silently replacing only the first match like the native binding would.
Solutions
- Add the g flag to the RegExp (e.g. /pattern/g)
- If you only want one replacement, call replace() instead of replaceAll()
- When building RegExp dynamically, pass 'g' in the flags argument: new RegExp(pattern, 'g')
Example fix
// before s.replaceAll(/foo/, 'bar'); // TypeError // after s.replaceAll(/foo/g, 'bar');
Defensive patterns
Strategy: validation
Validate before calling
function assertGlobalRegExp(re) {
if (re instanceof RegExp && !re.global) throw new TypeError('replaceAll requires a global RegExp (g flag)');
} Type guard
function isGlobalRegExp(v: unknown): v is RegExp & { global: true } {
return v instanceof RegExp && v.global;
} Try / catch
try {
s.replaceAll(searchValue, replacement);
} catch (e) {
if (e instanceof TypeError && /non-global RegExp/.test(e.message)) {
s.replaceAll(new RegExp(searchValue.source, 'g'), replacement);
} else throw e;
} Prevention
- Always write regexes for replaceAll with the g flag
- Prefer string search values over RegExp when exact-literal replacement is intended
- Add a lint rule (require-unicode-regexp style) or unit test covering replaceAll regex usage
When it happens
Trigger: Calling magicString.replaceAll(/pattern/, replacement) where /pattern/ lacks the `g` flag — `if (!searchValue.global) throw new TypeError(...)` fires.
Common situations: Porting code from replace() to replaceAll() without adding the g flag; constructing a RegExp from a string pattern and forgetting { flags: 'g' }; copying regexes used with String.replace into replaceAll.
Related errors
- msg
- accessor decorators must return an object with get, set, or…
- Attempted to access private element on non-instance
- decorators must return a function or void 0
- Metadata keys must be symbols, received
AI-assisted analysis of rolldown/rolldown@91b44b9d7b (2026-09-07).
Data as JSON: /api/errors/6c82789c5a5b69bc.
Report an issue: GitHub.
Appendix: source
Thrown at packages/rolldown/src/binding-magic-string.ts:130
// - Non-global sticky: advance to match end, or reset to 0 on miss
// - Non-global non-sticky: lastIndex is not modified by .replace()
if (searchValue.global) {
searchValue.lastIndex = 0;
} else if (searchValue.sticky) {
searchValue.lastIndex = lastMatchEnd === -1 ? 0 : lastMatchEnd;
}
return this;
};
NativeBindingMagicString.prototype.replaceAll = function (
searchValue: string | RegExp,
replacement: string,
): any {
if (typeof searchValue === 'string') {
return nativeReplaceAll.call(this, searchValue, replacement);
}
if (!searchValue.global) {
throw new TypeError(
'MagicString.prototype.replaceAll called with a non-global RegExp argument',
);
}
searchValue.lastIndex = 0;
(this as any).replaceRegex(searchValue, replacement);
searchValue.lastIndex = 0;
return this;
};
export interface RolldownMagicString extends NativeBindingMagicString {
readonly isRolldownMagicString: true;
/** Accepts a string or RegExp pattern. RegExp supports `$&`, `$$`, and `$N` substitutions. */
replace(from: string | RegExp, to: string): this;
/** Accepts a string or RegExp pattern. RegExp must have the global (`g`) flag. */
replaceAll(from: string | RegExp, to: string): this;
}
type RolldownMagicStringConstructor = Omit<typeof NativeBindingMagicString, 'prototype'> & {View on GitHub (pinned to 91b44b9d7b)