{"record":{"id":"6db81a40eccecc3b","repo":"karatelabs/karate","slug":"string-prototype-matchall-called-with-a-non-global-regexp","errorCode":null,"errorMessage":"String.prototype.matchAll called with a non-global RegExp argument","messagePattern":"String\\.prototype\\.matchAll called with a non-global RegExp argument","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsStringPrototype.java","lineNumber":588,"sourceCode":"    private Object match(Context context, Object[] args) {\n        String s = thisString(context, \"match\");\n        if (args.length == 0 || args[0] == null || args[0] == Terms.UNDEFINED) {\n            return List.of(\"\");\n        }\n        JsRegex regex = (args[0] instanceof JsRegex r) ? r : new JsRegex(argString(args, 0, context));\n        return regex.match(s);\n    }\n\n    private Object matchAll(Context context, Object[] args) {\n        String s = thisString(context, \"matchAll\");\n        // Spec: if regexp is a RegExp object, it must have the global flag.\n        // Otherwise we coerce to a global RegExp (string-source patterns are auto-g).\n        final JsRegex regex;\n        if (args.length == 0 || args[0] == null || args[0] == Terms.UNDEFINED) {\n            regex = new JsRegex(\"\", \"g\");\n        } else if (args[0] instanceof JsRegex r) {\n            if (!r.global) {\n                throw JsErrorException.typeError(\"String.prototype.matchAll called with a non-global RegExp argument\");\n            }\n            regex = r;\n        } else {\n            regex = new JsRegex(argString(args, 0, context), \"g\");\n        }\n        java.util.regex.Matcher matcher = regex.javaPattern.matcher(s);\n        JsIterator iter = new JsIterator() {\n            boolean fetched;\n            boolean done;\n            JsArray pending;\n            // §22.2.6.9 @@matchAll clones the receiver's matching state: start\n            // from its current lastIndex, keep position iterator-local (the\n            // original regex is never mutated), honor sticky anchoring.\n            final boolean unicode = regex.flags.indexOf('u') >= 0;\n            int nextIndex = regex.currentLastIndex();\n\n            private void fetch() {\n                if (fetched || done) return;","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsStringPrototype.java#L570-L606","documentation":"This TypeError is thrown by String.prototype.matchAll when given a RegExp without the global ('g') flag. matchAll iterates all matches, which is only well-defined for global regexes; the spec explicitly forbids non-global patterns. Note plain strings are auto-coerced to a global regex, so this only fires for actual non-global RegExp objects.","triggerScenarios":"Calling str.matchAll(/foo/) where the regex lacks 'g'. Distinguish from match, which accepts non-global regexes. Passing a regex built programmatically with flags omitted ('' or 'i' instead of 'g').","commonSituations":"Reusing a test regex (from .test() usage, often non-global) with matchAll; constructing RegExp from user-supplied flags; switching from str.match to str.matchAll without changing flags.","solutions":["Add the g flag: str.matchAll(/foo/g)","Clone with the flag: new RegExp(r.source, r.flags + 'g') before matchAll","Check rgx.global before calling matchAll and normalize if false"],"exampleFix":"// before\nfor (const m of s.matchAll(/foo/)) {} // TypeError\n// after\nfor (const m of s.matchAll(/foo/g)) {}","handlingStrategy":"type-guard","validationCode":"const toGlobal = (r) => r instanceof RegExp ? new RegExp(r.source, r.flags.includes('g') ? r.flags : r.flags + 'g') : r;","typeGuard":"const isGlobalRegex = (r) => r instanceof RegExp && r.global;","tryCatchPattern":"try { return [...s.matchAll(rgx)]; } catch (e) { if (e instanceof TypeError && rgx instanceof RegExp) return [...s.matchAll(new RegExp(rgx.source, rgx.flags + 'g'))]; throw e; }","preventionTips":["Keep a dedicated global-flagged regex for matchAll instead of reusing test regexes","Build RegExp from user flags with 'g' appended for iteration use cases","Prefer passing plain strings to matchAll — they are auto-global"],"tags":["javascript","regex","type-error","iteration"],"backgroundTag":"invalid-argument-value","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}