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

  1. Keep all reads inside the try-with-resources block that opened the tree; re-open via ArchivePathTree.open() for later access
  2. Use the ArchivePathTree itself (which opens/closes per operation) instead of holding a long-lived OpenPathTree
  3. Ensure worker threads finish before closing the handle (synchronize/latch)
  4. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/4ac1c6b58106762f. Report an issue: GitHub.