{"record":{"id":"534c4c8dabb9d698","repo":"oracle/graal","slug":"document-is-locked-by","errorCode":null,"errorMessage":"Document is locked by {}","messagePattern":"Document is locked by (.+?)","errorType":"exception","errorClass":"LockedException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/parsing/model/GraphDocument.java","lineNumber":323,"sourceCode":"        public String getLockingOperation() {\n            return theLock.getOperationLabel();\n        }\n\n        public boolean tryBreakLock() {\n            return theLock.cancel();\n        }\n    }\n\n    /**\n     * Locks document for writing for one operation. The lock is NOT reentrant.\n     *\n     * @param operationLabel user-readable label of the lock owner.\n     * @param cancel optional; callback to cancel the operation\n     * @return lock instance\n     */\n    public synchronized DocumentLock writeLock(String operationLabel, Callable<Boolean> cancel) {\n        if (lock != null) {\n            throw new LockedException(\"Document is locked by \" + lock.getOperationLabel(), lock);\n        }\n        return lock = new DocumentLock(operationLabel, cancel);\n    }\n\n    /**\n     * Represents a lock on the document. During the lock, no other modifications are permitted\n     * (throw a {@link LockedException}). Lock owner may disable modification tracking, i.e. during\n     * load from file, the GraphDocument does not become modified.\n     * <p>\n     * Modification tracking is restored when the lock is released.\n     */\n    public final class DocumentLock implements AutoCloseable {\n        private final String operationLabel;\n        private final Callable<Boolean> cancelFunc;\n        private boolean unlocked;\n\n        public DocumentLock(String operationLabel, Callable<Boolean> cancelFunc) {\n            this.operationLabel = operationLabel;","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/parsing/model/GraphDocument.java#L305-L341","documentation":"GraphDocument.writeLock(operationLabel, cancel) grants a single non-reentrant exclusive lock for document modification. If a DocumentLock is already held (lock != null), a second writeLock call throws LockedException naming the current holder, so concurrent or nested writers cannot corrupt document state.","triggerScenarios":"Calling document.writeLock(...) while another operation holds the lock (e.g. a file load still in progress, or a nested writeLock inside code already running under a lock). The lock is explicitly NOT reentrant, so even the same thread re-locking throws.","commonSituations":"A background loader parsing a graph file while the UI (or another tool) tries to apply edits; nesting writeLock in helper methods that are themselves called under a lock; forgetting to close() a DocumentLock in a finally block so it stays held forever.","solutions":["Wrap every DocumentLock in try-with-resources (it is AutoCloseable) so it is always released","Pass the existing DocumentLock down into nested code instead of calling writeLock again; restructure so locking happens at one level","Before locking, check/await the current lock (catch LockedException or inspect the document state) and retry when the owning operation finishes"],"exampleFix":"// before\ntry (DocumentLock l = doc.writeLock(\"load\", null)) {\n    applyEdits(doc); // internally calls doc.writeLock(\"edit\") -> LockedException\n}\n\n// after: pass the lock, don't re-lock\ntry (DocumentLock l = doc.writeLock(\"load\", null)) {\n    applyEdits(doc, l);\n}","handlingStrategy":"try-catch","validationCode":"synchronized (doc) { /* can only peek whether a lock exists via attempting writeLock in a try/catch; no public isLocked() — track your own lock scope */ }","typeGuard":null,"tryCatchPattern":"try (DocumentLock l = doc.writeLock(label, cancel)) { ... }\ncatch (LockedException e) { /* e.getMessage() names the holder; queue the edit or retry after the operation completes */ }","preventionTips":["Always use try-with-resources for DocumentLock (AutoCloseable)","Never nest writeLock; pass the lock object down","Serialize document mutations through one owner (single writer thread/queue)"],"tags":["graphio","concurrency","locking","document-model"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}