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 error

View on GitHub (pinned to 2add963021)

Solutions

  1. Write through a write channel from gcs.create(resourceId, createOptions) or the FileSystem create() API instead.
  2. Guard shared/generic code: call write only on channels opened for writing (e.g. instanceof check against the write-channel type).
  3. 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

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


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/68de681b39d2d6e7. Report an issue: GitHub.