quarkusio/quarkus · error · java.lang.RuntimeException
Failed to access
Error message
Failed to access
What it means
OpenArchivePathTree (the open handle returned by ArchivePathTree.open()) validates it is still open inside its read lock before any read operation. Once the handle's close() has run — typically because the try-with-resources block exited — further reads throw RuntimeException('Failed to access <roots> because the FileSystem has been closed').
Source
Thrown at independent-projects/bootstrap/app-model/src/main/java/io/quarkus/paths/ArchivePathTree.java:418
public Path getPath(String resourceName) {
lock.readLock().lock();
try {
ensureOpen();
return resolveEntryPath(resourceName);
} finally {
lock.readLock().unlock();
}
}
/**
* Make sure you use this method inside a lock.
*/
private void ensureOpen() {
// let's not use isOpen() as ensureOpen() is always used inside a read lock
if (open) {
return;
}
throw new RuntimeException("Failed to access " + ArchivePathTree.this.getRoots()
+ " because the FileSystem has been closed");
}
@Override
public void close() throws IOException {
lock.writeLock().lock();
try {
open = false;
rootPath = null;
fs.close();
} catch (IOException e) {
throw e;
} finally {
// even when we close the fs, everything is kept as is in the fs instance
// and typically the cen, which is quite large
// let's make sure the fs is nullified for it to be garbage collected
fs = null;
lock.writeLock().unlock();View on GitHub (pinned to e1c734241f)
Solutions
- Keep all reads inside the try-with-resources block that opened the tree; re-open via ArchivePathTree.open() for later access
- Use the ArchivePathTree itself (which opens/closes per operation) instead of holding a long-lived OpenPathTree
- Ensure worker threads finish before closing the handle (synchronize/latch)
- Do not cache OpenPathTree instances; cache the ArchivePathTree and open on demand
Example fix
// before
OpenPathTree open = tree.open();
open.walk(visitor);
open.close();
open.contains("x"); // throws: closed
// after
try (OpenPathTree open = tree.open()) {
open.walk(visitor);
open.contains("x");
} Defensive patterns
Strategy: try-catch
Validate before calling
// ensure all reads happen inside the open scope
try (OpenPathTree open = tree.open()) {
// all reads here only
} Type guard
boolean usable(OpenPathTree t) {
try { t.contains("META-INF/MANIFEST.MF"); return true; }
catch (RuntimeException e) { return false; } // closed FS
} Try / catch
try {
open.walk(visitor);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("has been closed")) {
try (OpenPathTree reopened = tree.open()) { reopened.walk(visitor); }
} else { throw e; }
} Prevention
- Never let OpenPathTree references escape try-with-resources scope
- Coordinate async workers with latches before closing handles
- Cache ArchivePathTree, not OpenPathTree instances
- Re-open per operation instead of reusing closed handles
When it happens
Trigger: Calling apply/accept/walk/walkRaw/walkIfContains/contains on an OpenPathTree obtained from ArchivePathTree.open() after that handle was closed, e.g. using it outside the try-with-resources scope, storing it in a field, or using it from another thread after close.
Common situations: Keeping a reference to the open tree beyond the try-with-resources block; async/worker threads reading a handle the main thread already closed; caching OpenPathTree instances for reuse.
Related errors
- Can only sync state on the server side of remote dev mode
- All parameters have already been loaded, it is too late to c
- Internal error: An attempt was made to start an application
- Cannot reset a started application
- The application is stopping
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/4ac1c6b58106762f.
Report an issue: GitHub.