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();
}
@OverrideView on GitHub (pinned to f213380f81)
Solutions
- Replace File-based logic with NIO Path APIs (Files.exists(path), Files.newInputStream(path)) which work through the provider
- Branch on path type and use local handling only for non-StoragePath inputs
- 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
- Use NIO Path APIs (Files.exists/newInputStream/readAttributes) instead of File in storage-facing code
- Refactor File-based APIs to accept Path
- Ban path.toFile() in code that receives abstraction-resolved paths (lint rule/review checklist)
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
- A storage path can only resolve another storage path within
- A storage path can only relativize another storage path with
- compared storage paths must be from the same storage system
- register
- Path provided is not a StoragePath:
AI-assisted analysis of neo4j/neo4j@f213380f81 (2026-08-14).
Data as JSON: /api/errors/aeb5854e03f83205.
Report an issue: GitHub.