apache/flink · error · IOException
WriteChannel.write wrote %d of %d requested bytes, failing.
Error message
WriteChannel.write wrote %d of %d requested bytes, failing.
What it means
After delegating to the Google Storage WriteChannel, the code checks that the number of bytes the channel reports as written equals the requested length. Recoverable writers must not produce partial writes, so any short write is turned into a failing IOException rather than silently losing data. In practice a WritableByteChannel should write everything or throw, so this indicates abnormal channel behavior.
Source
Thrown at flink-filesystems/flink-gs-fs-hadoop/src/main/java/org/apache/flink/fs/gs/writer/GSRecoverableFsDataOutputStream.java:164
throw new IOException("Illegal attempt to write to closed output stream");
}
// if necessary, create a write channel
if (currentWriteChannel == null) {
LOGGER.debug("Creating write channel for blob {}", finalBlobIdentifier);
currentWriteChannel = createWriteChannel();
}
// write to the stream. the docs say that, in some circumstances, though an attempt will be
// made to write all of the requested bytes, there are some cases where only some bytes will
// be written. it's not clear whether this could ever happen with a Google storage
// WriteChannel; in any case, recoverable writers don't support partial writes, so if this
// ever happens, we must fail the write.:
// https://docs.oracle.com/javase/7/docs/api/java/nio/channels/WritableByteChannel.html#write(java.nio.ByteBuffer)
LOGGER.trace("Writing {} bytes", length);
int bytesWritten = currentWriteChannel.write(content, start, length);
if (bytesWritten != length) {
throw new IOException(
String.format(
"WriteChannel.write wrote %d of %d requested bytes, failing.",
bytesWritten, length));
}
// update count of total bytes written
position += bytesWritten;
}
@Override
public void flush() throws IOException {
LOGGER.trace("Flushing write channel for blob {}", finalBlobIdentifier);
closeWriteChannelIfExists();
}
@Override
public void sync() throws IOException {
LOGGER.trace("Syncing write channel for blob {}", finalBlobIdentifier);View on GitHub (pinned to 2f3c205e92)
Solutions
- Retry the operation at the job level: the sink will reopen/resume from the last persisted recoverable (this error is designed to fail fast)
- Upgrade the Google Cloud Storage Hadoop client library used by the plugin to pick up channel fixes
- If reproducible, reduce write chunk sizes in the sink so each write() call is smaller and capture client logs to identify the transport failure
Defensive patterns
Strategy: retry
Try / catch
try {
stream.write(buf, 0, len);
} catch (IOException e) {
// short write: fail the attempt; on restart the sink resumes from the last
// persisted GSResumeRecoverable, which discards the unflushed tail
throw e;
} Prevention
- Persist recoverables (keep()) at regular intervals so retries lose little data
- Keep the GCS client library current
- Do not catch-and-continue on partial writes; data would be silently lost
When it happens
Trigger: currentWriteChannel.write(content, start, length) returning fewer bytes than length during GSRecoverableFsDataOutputStream.write; can only happen if the GCS Java client channel performs a short write (e.g. under transport interruption or client-library anomalies) instead of throwing.
Common situations: Transient network/HTTP2 stream failures inside the Google Cloud Storage client; a GCS client library version with non-blocking short-write behavior; extremely large single write() calls hitting client internal limits.
Related errors
- Illegal attempt to write to closed output stream
- Failed to get object for key: {}
- Error while waiting for job to be initialized
- Could not build the program from JAR file: {}
- Could not cancel job {}.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/ac0e77f800b657a6.
Report an issue: GitHub.