apache/beam · error · UnsupportedOperationException
GcsSeekableByteChannels are read-only and cannot be truncate
Error message
GcsSeekableByteChannels are read-only and cannot be truncated.
What it means
GcsUtilV2's GcsSeekableByteChannel is a read-only channel over a GCS object; truncate(long) unconditionally throws UnsupportedOperationException, as does write(). The channel API contract includes truncate for read-write channels, so the read-only implementation must reject it.
Source
Thrown at sdks/java/extensions/google-cloud-platform-core/src/main/java/org/apache/beam/sdk/extensions/gcp/util/GcsUtilV2.java:539
checkArgument(newPosition >= 0, "Position must be non-negative: %s", newPosition);
reader.seek(newPosition);
this.position = newPosition;
return this;
}
@Override
public long position() throws IOException {
return this.position;
}
@Override
public long size() throws IOException {
return size;
}
@Override
public SeekableByteChannel truncate(long size) throws IOException {
throw new UnsupportedOperationException(
"GcsSeekableByteChannels are read-only and cannot be truncated.");
}
@Override
public int write(ByteBuffer src) throws IOException {
throw new UnsupportedOperationException(
"GcsSeekableByteChannel are read-only and does not support writing.");
}
@Override
public boolean isOpen() {
return reader.isOpen();
}
@Override
public void close() throws IOException {
if (isOpen()) {
reader.close();View on GitHub (pinned to 12126d8942)
Solutions
- Don't truncate GCS read channels; to 'shrink' an object, copy the desired byte range to a new object and delete/replace the original.
- Check channel writability before truncate: use instanceof/capability checks or try-catch UnsupportedOperationException.
- For local filesystem operations, use a local channel, not the GCS one.
- If writable GCS channels are needed, use the write path (WriteChannel via create/update) rather than SeekableByteChannel.truncate.
Example fix
// before
channel.truncate(newSize); // UnsupportedOperationException on GCS channel
// after
if (channel instanceof GcsUtilV2.GcsSeekableByteChannel) {
throw new IllegalStateException("GCS channels are read-only; copy range to new object instead");
} Defensive patterns
Strategy: type-guard
Type guard
static boolean isWritableChannel(SeekableByteChannel ch) {
return !(ch instanceof GcsUtilV2.GcsSeekableByteChannel);
} Try / catch
try {
channel.truncate(size);
} catch (UnsupportedOperationException e) {
// GCS read channel: perform range-copy to a new object instead
} Prevention
- Never pass GCS-backed channels to java.nio code that truncates or writes
- Model GCS 'shrink' as range-copy to a new object plus delete
- Use GCS write channels (create/update) for any write-like operation
When it happens
Trigger: Calling SeekableByteChannel.truncate(size) on a channel obtained from gcsUtil.open (GCS read channel), directly or via file-manipulation utilities (e.g. Files.newByteChannel + truncate, or copy-with-replace helpers that assume writable channels).
Common situations: Passing a GCS-backed channel to generic java.nio file code that assumes local-file semantics; attempting in-place size adjustments of remote objects; test code reusing channel helpers written for local filesystems.
Related errors
- Skipping dest existence is only supported within a bucket.
- GcsSeekableByteChannel are read-only and does not support wr
- Runner does not support draining.
- Unknown DirectoryTreatment: " + directoryTreatment
- Support for move options is not yet implemented.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/feb2440e43261d00.
Report an issue: GitHub.