{"record":{"id":"93e43de53702b5e2","repo":"stanfordnlp/CoreNLP","slug":"this-is-an-unmodifiable-view","errorCode":null,"errorMessage":"This is an unmodifiable view!","messagePattern":"This is an unmodifiable view!","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"src/edu/stanford/nlp/util/HashIndex.java","lineNumber":487,"sourceCode":"  public Iterator<E> iterator() {\n    return objects.iterator();\n  }\n\n  /**\n   * Returns an unmodifiable view of the Index.  It is just\n   * a locked index that cannot be unlocked, so if you\n   * try to add something, nothing will happen (it won't throw\n   * an exception).  Trying to unlock it will throw an\n   * UnsupportedOperationException.  If the\n   * underlying Index is modified, the change will\n   * \"write-through\" to the view.\n   *\n   * @return An unmodifiable view of the Index\n   */\n  public HashIndex<E> unmodifiableView() {\n    HashIndex<E> newIndex = new HashIndex<E>(objects, indexes) {\n      @Override\n      public void unlock() { throw new UnsupportedOperationException(\"This is an unmodifiable view!\"); }\n      private static final long serialVersionUID = 3415903369787491736L;\n    };\n    newIndex.lock();\n    return newIndex;\n  }\n\n  /**\n   * This assumes each line is one value and creates index by adding values in the order of the lines in the file\n   * @param file Which file to load\n   * @return An index built out of the lines in the file\n   */\n  public static Index<String> loadFromFileWithList(String file) {\n    Index<String> index = new HashIndex<>();\n    try (BufferedReader br = new BufferedReader(new FileReader(file))) {\n      for (String line; (line = br.readLine()) != null; ) {\n        index.add(line.trim());\n      }\n    } catch (Exception e) {","sourceCodeStart":469,"sourceCodeEnd":505,"githubUrl":"https://github.com/stanfordnlp/CoreNLP/blob/1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a/src/edu/stanford/nlp/util/HashIndex.java#L469-L505","documentation":"HashIndex.unmodifiableView() returns a read-only view whose unlock() override always throws UnsupportedOperationException. Calling unlock() (or methods that rely on it to mutate the index) on such a view is rejected by design.","triggerScenarios":"Calling unlock(), or any mutating method that first checks/needs locking, on the HashIndex returned by unmodifiableView().","commonSituations":"Code that generically locks/unlocks Index instances encountering a view created as unmodifiable; trying to add elements to a view returned from an API documented as read-only.","solutions":["Keep a reference to the original mutable HashIndex and mutate that instead of the view","Call unmodifiableView() only at the point you need read-only access, and use the original elsewhere","Remove the unlock()/mutation call if the object is intentionally read-only"],"exampleFix":"// before\nHashIndex<E> view = original.unmodifiableView();\nview.unlock(); // throws\n// after\noriginal.unlock(); // mutate the underlying index, not the view","handlingStrategy":"validation","validationCode":"if (isUnmodifiableView(index)) { /* use original reference for mutation */ }","typeGuard":"boolean isUnmodifiableView(HashIndex<?> idx) { try { idx.unlock(); idx.lock(); return false; } catch (UnsupportedOperationException e) { return true; } }","tryCatchPattern":"try { index.unlock(); } catch (UnsupportedOperationException e) { /* obtain the underlying mutable index instead */ }","preventionTips":["Treat objects from unmodifiableView() as strictly read-only","Keep the original HashIndex reference handy for mutations","Document read-only views at API boundaries"],"tags":["unmodifiable","unsupported-operation","index"],"backgroundTag":"unsupported-operation","analyzedSha":"1b7edd19c4d0d7b1f13a2591425b9b60a0b1af7a","analyzedAt":"2026-09-10T02:24:07.274Z","contentChangedAt":"2026-09-10T02:24:07.274Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}