stanfordnlp/CoreNLP · error · UnsupportedOperationException

Unknown position in AddDep: |${position}|

Error message

Unknown position in AddDep: |${position}|

What it means

At evaluation time AddDep switches on the stored position string to compute the new node's index; if the position is a non-null value that was not one of the recognized signed-offset forms (or a legacy value the switch no longer handles), evaluate throws this UnsupportedOperationException. Unlike error 976, this fires at runtime during Ssurgeon execution, indicating a position format the constructor did not reject but evaluate cannot interpret.

Solutions

  1. Change the position to a recognized signed form: negative (insert before target), positive (insert after target), or null for default end placement.
  2. Re-check the Ssurgeon rule file: the exception prints the raw position between pipes (|value|), which usually reveals whitespace or an unexpected literal.
  3. Update to a CoreNLP version whose AddDep constructor rejects the bad position up front (error 976) instead of failing at evaluate time.
  4. Catch UnsupportedOperationException in the Ssurgeon driver and log the failing rule plus position for the rule author.

Example fix

// before
new AddDep("gov", rel, attrs, "0"); // parses, fails in evaluate()
// after
new AddDep("gov", rel, attrs, null); // default placement, or "+1"/"-1"
Defensive patterns

Strategy: try-catch

Validate before calling

if (position != null && !(position.startsWith("-") || position.startsWith("+"))) position = null; // fall back to default placement

Try / catch

try { addDep.evaluate(sg, match, env); } catch (UnsupportedOperationException e) { log.error("AddDep bad position: {}", addDep); throw e; }

Prevention

When it happens

Trigger: Executing an AddDep operation whose position string reaches the else-branch of the index computation in evaluate() — e.g. a position like "0", " ", or a format accepted upstream but not matched by any case in the switch, on a graph where target.index() arithmetic cannot apply.

Common situations: Mixing Ssurgeon rule versions where position semantics changed; positions built programmatically as unsigned or descriptive strings; rules migrated between CoreNLP versions with different accepted position values.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/6d656eb155bcdf24. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/semgraph/semgrex/ssurgeon/AddDep.java:126

      tempIndex = SemanticGraphUtils.maxIndex(sg) + 2;

      if (position.equals("-")) {
        newIndex = SemanticGraphUtils.minIndex(sg);
      } else if (position.startsWith("-") || position.startsWith("+")) {
        String targetName = position.substring(1);
        IndexedWord target = sm.getNode(targetName);
        if (target == null) {
          return false;
        }
        if (position.startsWith("-")) {
          // it will be exactly to the left rather than pushing over
          // something a word earlier if we do .index(), not .index() - 1
          newIndex = target.index();
        } else {
          newIndex = target.index() + 1;
        }
      } else {
        throw new UnsupportedOperationException("Unknown position in AddDep: |" + position + "|");
      }
    } else {
      tempIndex = SemanticGraphUtils.maxIndex(sg) + 1;
      newIndex = -1;
    }

    newNode.setDocID(govNode.docID());
    newNode.setIndex(tempIndex);
    newNode.setSentIndex(govNode.sentIndex());

    sg.addVertex(newNode);
    sg.addEdge(govNode, newNode, relation, weight, false);

    if (position != null && !position.equals("+")) {
      // the payoff for tempIndex == maxIndex + 2:
      // everything will be moved one higher, unless it's the new node
      SsurgeonUtils.moveNodes(sg, sm, x -> (x >= newIndex && x != tempIndex), x -> x+1, true);
      SsurgeonUtils.moveNode(sg, sm, newNode, newIndex);

View on GitHub (pinned to 1b7edd19c4)