A reused global or sticky regular expression carries lastIndex state between tests. Use a nonstateful expression for independent validation, or intentionally reset the cursor before each independent test.
Reproduce the behavior safely
Run this self-contained fixture in an empty temporary directory, separate from your project. Shell examples create only named fixture files there. JavaScript examples use local values and send no network requests.
const assert = require('node:assert/strict');
const cursor = /cat/g;
const first = cursor.test('cat');
const afterFirst = cursor.lastIndex;
const second = cursor.test('cat');
assert.equal(first, true);
assert.equal(afterFirst, 3);
assert.equal(second, false);
assert.equal(cursor.lastIndex, 0);
const validator = /^cat$/;
assert(validator.test('cat') && validator.test('cat'));
cursor.lastIndex = 0;
assert.equal(cursor.test('cat'), true);
console.log(JSON.stringify({first, afterFirst, second}));Observed local output
{"first":true,"afterFirst":3,"second":false}Why the result changes
The second call begins at the saved cursor, rather than at the start of a fresh independent search. The failed search resets that cursor in this example. Logging only the pattern text and input hides the mutable state. A validator without g or y avoids this particular cursor behavior; anchors separately choose whether the whole input must match.
Choose and verify the correction
Inspect flags and lastIndex on the exact regex instance reused by your validation loop. Remove global or sticky mode when you need independent boolean validation. For intentional scanning, keep the state but control the input and cursor lifecycle. When a library accepts a shared regex, check whether it retains and reuses the instance. Add two identical consecutive inputs to your fixture so a single passing call cannot hide the issue.
Limits and next checks
The example covers test on a simple global expression in Node. Other regex methods have their own cursor interactions. Removing g does not fix a pattern that accepts an unintended substring; validation scope and cursor state are separate decisions. Sticky mode and empty matches need deliberate iteration handling. Do not use a broad pattern as a replacement for parsing a structured format.
Related: Async Filter Keeps Rejected Items: Resolve Decisions Before Filtering.
Isolated fixture executed on macOS on November 10, 2026 (KST), with v26.5.0. The observed output verifies this example, not every application or runtime.