apache/hadoop · error · UnsupportedOperationException
Cannot mutate read-only channel
Error message
Cannot mutate read-only channel
What it means
write(ByteBuffer) on GoogleCloudStorageClientReadChannel always throws UnsupportedOperationException. The class only implements it because SeekableByteChannel requires the method; the channel is strictly read-only and all reads are served through its internal ContentReadChannel. There is no code path that ever accepts a write.
Source
Thrown at hadoop-cloud-storage-project/hadoop-gcp/src/main/java/org/apache/hadoop/fs/gs/GoogleCloudStorageClientReadChannel.java:114
@Override
public int read(ByteBuffer dst) throws IOException {
throwIfNotOpen();
// Don't try to read if the buffer has no space.
if (dst.remaining() == 0) {
return 0;
}
LOG.trace(
"Reading {} bytes at {} position from '{}'", dst.remaining(), currentPosition, resourceId);
if (currentPosition == objectSize) {
return -1;
}
return contentReadChannel.readContent(dst);
}
@Override
public int write(ByteBuffer src) throws IOException {
throw new UnsupportedOperationException("Cannot mutate read-only channel");
}
@Override
public long position() throws IOException {
return currentPosition;
}
/**
* Sets this channel's position.
*
* <p>This method will throw an exception if {@code newPosition} is greater than object size,
* which contradicts {@link SeekableByteChannel#position(long) SeekableByteChannel} contract.
* TODO(user): decide if this needs to be fixed.
*
* @param newPosition the new position, counting the number of bytes from the beginning.
* @return this channel instance
* @throws FileNotFoundException if the underlying object does not exist.
* @throws IOException on IO errorView on GitHub (pinned to 2add963021)
Solutions
- Write through a write channel from gcs.create(resourceId, createOptions) or the FileSystem create() API instead.
- Guard shared/generic code: call write only on channels opened for writing (e.g. instanceof check against the write-channel type).
- For in-place modification, read the object, modify bytes, and rewrite it as a new object (GCS objects are immutable).
Example fix
// before
try (SeekableByteChannel ch = gcs.open(itemId)) {
ch.write(buf); // UnsupportedOperationException
}
// after
try (WritableByteChannel out = gcs.create(dstId, CreateFileOptions.DEFAULT)) {
out.write(buf);
} Defensive patterns
Strategy: type-guard
Type guard
static boolean isReadOnlyChannel(SeekableByteChannel ch) {
return ch instanceof GoogleCloudStorageClientReadChannel;
} Prevention
- Keep read and write paths separate: open read channels for reads, gcs.create() write channels for writes.
- In generic copy utilities, branch on instanceof rather than probing with write().
- Remember GCS objects are immutable — design for read-then-rewrite, never in-place mutation.
When it happens
Trigger: Calling write(...) on a channel obtained from gcs.open(...) / GoogleCloudStorageClientReadChannel.create — generic adapter code that uses one SeekableByteChannel for both directions, tests exercising the interface, or code ported from FileChannel.
Common situations: Utility copy routines that try both directions on the same channel; porting local-filesystem code where RandomAccessFile/FileChannel is writable; frameworks probing writability with a probe write.
Related errors
- This operation is not supported across two different buckets
- This operation is not supported across two different storage
- This operation is not supported across two different storage
- Moving object from bucket '%s' to '%s' is not supported
- Metrics are read-only.
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/68de681b39d2d6e7.
Report an issue: GitHub.