neo4j/neo4j · error · UnsupportedOperationException

Storage paths cannot be converted to File objects

Error message

Storage paths cannot be converted to File objects

What it means

StoragePath.toFile() throws UnsupportedOperationException because the path denotes an object in remote cloud storage that has no representation as a java.io.File (which is inherently local). The class chooses to fail fast rather than return a meaningless File pointing at a non-existent local location.

Source

Thrown at community/cloud/src/main/java/org/neo4j/cloud/storage/StoragePath.java:382

    public int compareTo(Path other) {
        final var storagePath = ensureStoragePath(other);
        if (storagePath.storage != this.storage) {
            throw new ClassCastException("compared storage paths must be from the same storage system");
        }

        return toRealPath(NOFOLLOW_LINKS)
                .toString()
                .compareTo(storagePath.toRealPath(NOFOLLOW_LINKS).toString());
    }

    @Override
    public Iterator<Path> iterator() {
        return new StoragePathIterator(path.elements().iterator(), path.isAbsolute(), path.hasTrailingSeparator());
    }

    @Override
    public File toFile() {
        throw new UnsupportedOperationException("Storage paths cannot be converted to File objects");
    }

    @Override
    public WatchKey register(WatchService watcher, Kind<?>[] events, Modifier... modifiers) {
        throw new UnsupportedOperationException("register");
    }

    @Override
    public WatchKey register(WatchService watcher, Kind<?>... events) {
        throw new UnsupportedOperationException("register");
    }

    @Override
    public String toString() {
        return path.toString();
    }

    @Override

View on GitHub (pinned to f213380f81)

Solutions

  1. Replace File-based logic with NIO Path APIs (Files.exists(path), Files.newInputStream(path)) which work through the provider
  2. Branch on path type and use local handling only for non-StoragePath inputs
  3. For metadata (name, parent), use getFileName()/getParent() instead of File's name/parent methods

Example fix

// before
File f = path.toFile(); // throws
boolean exists = f.exists();

// after
boolean exists = Files.exists(path);
InputStream in = Files.newInputStream(path);
Defensive patterns

Strategy: type-guard

Validate before calling

boolean fileConvertible(Path p) {
    return !(p instanceof org.neo4j.cloud.storage.StoragePath);
}

Type guard

static boolean isLocalPath(Path p) {
    return !(p instanceof org.neo4j.cloud.storage.StoragePath);
}

Try / catch

catch (UnsupportedOperationException e) on toFile(): switch the code path to NIO (Files.*) APIs which dispatch through the provider.

Prevention

When it happens

Trigger: Calling toFile() on a StoragePath — directly or via APIs that convert Path to File (legacy config loaders, File-based tooling, libraries calling path.toFile().exists() and friends).

Common situations: Legacy code predating NIO that works with File objects being handed cloud paths; third-party libraries accepting File arguments; plugins copying local-file idioms; toString()-derived File construction in configs.

Related errors


AI-assisted analysis of neo4j/neo4j@f213380f81 (2026-08-14). Data as JSON: /api/errors/aeb5854e03f83205. Report an issue: GitHub.