oracle/graal · error · LockedException
Document is locked by {}
Error message
Document is locked by {} What it means
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.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/parsing/model/GraphDocument.java:323
public String getLockingOperation() {
return theLock.getOperationLabel();
}
public boolean tryBreakLock() {
return theLock.cancel();
}
}
/**
* Locks document for writing for one operation. The lock is NOT reentrant.
*
* @param operationLabel user-readable label of the lock owner.
* @param cancel optional; callback to cancel the operation
* @return lock instance
*/
public synchronized DocumentLock writeLock(String operationLabel, Callable<Boolean> cancel) {
if (lock != null) {
throw new LockedException("Document is locked by " + lock.getOperationLabel(), lock);
}
return lock = new DocumentLock(operationLabel, cancel);
}
/**
* Represents a lock on the document. During the lock, no other modifications are permitted
* (throw a {@link LockedException}). Lock owner may disable modification tracking, i.e. during
* load from file, the GraphDocument does not become modified.
* <p>
* Modification tracking is restored when the lock is released.
*/
public final class DocumentLock implements AutoCloseable {
private final String operationLabel;
private final Callable<Boolean> cancelFunc;
private boolean unlocked;
public DocumentLock(String operationLabel, Callable<Boolean> cancelFunc) {
this.operationLabel = operationLabel;View on GitHub (pinned to a66e9ccd1d)
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
Example fix
// before
try (DocumentLock l = doc.writeLock("load", null)) {
applyEdits(doc); // internally calls doc.writeLock("edit") -> LockedException
}
// after: pass the lock, don't re-lock
try (DocumentLock l = doc.writeLock("load", null)) {
applyEdits(doc, l);
} Defensive patterns
Strategy: try-catch
Validate before calling
synchronized (doc) { /* can only peek whether a lock exists via attempting writeLock in a try/catch; no public isLocked() — track your own lock scope */ } Try / catch
try (DocumentLock l = doc.writeLock(label, cancel)) { ... }
catch (LockedException e) { /* e.getMessage() names the holder; queue the edit or retry after the operation completes */ } Prevention
- 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)
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Trying to write during graph print.
- Expecting
- Error deleting %s. This is most likely due to a compilation
- Cannot downgrade from minimum required version
- Feature unsupported in version
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/534c4c8dabb9d698.
Report an issue: GitHub.