antlr/antlr4 · error · Error

should only be one op per index

Error message

should only be one op per index

What it means

OrderedHashSet.remove(Object) is hard-coded to throw UnsupportedOperationException (with an empty message) because the class must keep its LinkedHashMap and backing elements list consistent; the ANTLR authors simply did not implement ordered removal. OrderedHashSet backs ParserRuleContext children sets and rule-stop-state bookkeeping, so removal was never needed by the runtime.

Source

Thrown at runtime/JavaScript/src/antlr4/TokenStreamRewriter.js:313

                    rop.text = this.catOpText(iop.text, rop.text);
                    rewrites[i] = undefined;	// delete current insert
                    continue;
                }
                if (iop.index >= rop.index && iop.index <= rop.lastIndex) {
                    throw new Error(`insert op ${iop} within boundaries of previous ${rop}`);
                }
            }
        }

        /** @type {Map<number, RewriteOperation>} */
        let m = new Map();
        for (let op of rewrites) {
            if (op == null) {
                // ignore deleted ops
                continue;
            }
            if (m.get(op.index) != null) {
                throw new Error("should only be one op per index");
            }
            m.set(op.index, op);
        }
        return m;
    }

    /**
     * @param {Text} a
     * @param {Text} b
     * @returns {string}
     */
    catOpText(a, b) {
        let x = "";
        let y = "";
        if (a != null) {
            x = a.toString();
        }
        if (b != null) {

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Use java.util.LinkedHashSet (or ArrayDeque-based structure) if you need ordered removal semantics.
  2. Call clear() and re-add the remaining elements when a full rebuild is acceptable.
  3. Wrap the set in a class that exposes only the operations actually supported.

Example fix

// before
OrderedHashSet<Token> tokens = new OrderedHashSet<>();
tokens.remove(t); // UnsupportedOperationException

// after
LinkedHashSet<Token> tokens = new LinkedHashSet<>();
tokens.remove(t);
Defensive patterns

Strategy: type-guard

Type guard

boolean supportsRemove(Collection<?> c) { return !(c instanceof OrderedHashSet); }

Try / catch

try {
    set.remove(o);
} catch (UnsupportedOperationException e) {
    // rebuild instead of remove
    Object keep = ...;
    set.clear();
    set.add(keep);
}

Prevention

When it happens

Trigger: Calling remove(Object o) on any OrderedHashSet instance, e.g. a rule context's children set, or an OrderedHashSet you instantiated yourself.

Common situations: Treating OrderedHashSet as a general-purpose Set implementation; refactoring application collections to OrderedHashSet and assuming the full Set contract is honored.

Related errors


AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14). Data as JSON: /api/errors/074fb5223ceba00a. Report an issue: GitHub.