neo4j/neo4j · error · UnsupportedOperationException
Not supported in storage channels
Error message
Not supported in storage channels
What it means
StorageChannel implements a positional write API surface (it mirrors Neo4j's ReadableChannel/WritableChannel contracts) but the underlying cloud channel only supports sequential writes — remote storage is typically append/stream oriented and cannot cheaply seek-and-write. writeAll(ByteBuffer, long position) therefore throws UnsupportedOperationException to fail fast on positional semantics.
Source
Thrown at community/cloud/src/main/java/org/neo4j/cloud/storage/StorageChannel.java:77
return write(srcs, 0, srcs.length);
}
@Override
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
Preconditions.checkArgument(
offset >= 0 && offset < srcs.length, "Offset must be within the range of buffers provided");
Preconditions.checkArgument(
offset + length <= srcs.length, "Length must be within the range of buffers provided");
var written = 0L;
for (var i = offset; i < offset + length; i++) {
written += doWrite(srcs[i]);
}
return written;
}
@Override
public void writeAll(ByteBuffer src, long position) throws IOException {
throw new UnsupportedOperationException("Not supported in storage channels");
}
@Override
public void writeAll(ByteBuffer src) throws IOException {
doWrite(src);
}
@Override
public StorageChannel truncate(long size) throws IOException {
channel.truncate(size);
return this;
}
@Override
public int read(ByteBuffer dst, long position) throws IOException {
//noinspection resource
return position(position).read(dst);
}View on GitHub (pinned to f213380f81)
Solutions
- Use the sequential API: position(pos) followed by writeAll(src) (single-argument), which is supported
- Rewrite generic copy helpers to check channel type and use sequential writes for StorageChannel
- Buffer writes in memory (or a local temp channel) and stream them sequentially to storage
Example fix
// before channel.writeAll(buffer, 42L); // throws // after channel.position(42L); channel.writeAll(buffer);
Defensive patterns
Strategy: validation
Validate before calling
void writeAllAt(StorageChannel ch, ByteBuffer src, long pos) throws IOException {
ch.position(pos); // supported
ch.writeAll(src); // sequential overload, supported
} Type guard
static boolean supportsPositionalWrite(ReadableChannel ch) {
return !(ch instanceof org.neo4j.cloud.storage.StorageChannel);
} Try / catch
catch (UnsupportedOperationException e) on writeAll(src, pos): retry once via position(pos)+writeAll(src); rethrow if that also fails.
Prevention
- Write IO helpers against the sequential overloads only
- Type-check channels in shared copy utilities before choosing positional overloads
- Keep a lint/review check for the two-argument writeAll/readAll on abstraction-provided channels
When it happens
Trigger: Calling storageChannel.writeAll(src, position) — the two-argument positional variant — directly, or via framework code that uses positional writes when a channel happens to be a StorageChannel (e.g. generic copy utilities that always call the positional overload).
Common situations: Reusing file-copy or page-flush utilities written against StoreChannel/FileChannel with cloud storage channels; migrating code from LocalFileSystemAbstraction channels to cloud storage; third-party libs that call FileChannel-style positional writes.
Related errors
- Channel has reached end-of-stream.
- tryLock
- getPositionLock
- Unable to write to disk, reported bytes written was
- Already read from the path:
AI-assisted analysis of neo4j/neo4j@f213380f81 (2026-08-14).
Data as JSON: /api/errors/2d30460b428d6c8b.
Report an issue: GitHub.