{"record":{"id":"a1edf007a56271f3","repo":"antlr/antlr4","slug":"index-cannot-be-negative","errorCode":null,"errorMessage":"index cannot be negative","messagePattern":"index cannot be negative","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"runtime/JavaScript/src/antlr4/misc/BitSet.js","lineNumber":110,"sourceCode":"\n    get length() {\n        return this.data.map(l => BitSet._bitCount(l)).reduce((s, v) => s + v, 0);\n    }\n\n    _resize(index) {\n        const count = index + 32 >>> 5;\n        if (count <= this.data.length) {\n            return;\n        }\n        const data = new Uint32Array(count);\n        data.set(this.data);\n        data.fill(0, this.data.length);\n        this.data = data;\n    }\n\n    static _checkIndex(index) {\n        if (index < 0)\n            throw new RangeError(\"index cannot be negative\");\n    }\n\n    static _bitCount(l) {\n        // see https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel\n        let count = 0;\n        l = l - ((l >> 1) & 0x55555555);\n        l = (l & 0x33333333) + ((l >> 2) & 0x33333333);\n        l = (l + (l >> 4)) & 0x0f0f0f0f;\n        l = l + (l >> 8);\n        l = l + (l >> 16);\n        return count + l & 0x3f;\n    }\n}\n","sourceCodeStart":92,"sourceCodeEnd":124,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/JavaScript/src/antlr4/misc/BitSet.js#L92-L124","documentation":"The companion check in setDelimiters for the stop delimiter: it must be non-null and non-empty because the scanner needs a concrete terminator to find each tag's end. An empty stop would make indexOf return immediately-adjacent positions and break tag boundary detection, so the method rejects it with IllegalArgumentException.","triggerScenarios":"Calling setDelimiters(\"{\", \"\", ...) or with a null stop when configuring custom pattern tag syntax.","commonSituations":"Same custom-delimiter scenario as the start check; typically a typo, a constants class returning empty string, or reading delimiters from a properties file where the stop key is missing.","solutions":["Pass a valid stop delimiter: setDelimiters(\"{\", \"}\", \"\\\\\").","Assert both delimiters are non-empty when loading them from configuration.","Unit-test the delimiter configuration separately from pattern compilation."],"exampleFix":"// before\nmatcher.setDelimiters(\"{\", cfg.get(\"stop\"), \"\\\\\"); // empty string -> IllegalArgumentException\n\n// after\nString stop = cfg.get(\"stop\");\nif (stop == null || stop.isEmpty()) throw new ConfigException(\"pattern stop delimiter missing\");\nmatcher.setDelimiters(\"{\", stop, \"\\\\\");","handlingStrategy":"validation","validationCode":"if (stop == null || stop.isEmpty()) throw new ConfigException(\"stop delimiter required\");\nmatcher.setDelimiters(start, stop, escape);","typeGuard":"boolean isValidDelimiter(String d) { return d != null && !d.isEmpty(); }","tryCatchPattern":null,"preventionTips":["Assert both delimiters are non-empty before calling setDelimiters.","Fail configuration loading loudly when delimiter keys are missing.","Cover delimiter config in unit tests."],"tags":["antlr","java","parse-tree-pattern","configuration","validation"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}