apache/flink · error · UnsupportedOperationException
NoFetchingInput cannot prefetch data.
Error message
NoFetchingInput cannot prefetch data.
What it means
NoFetchingInput deliberately overrides canReadInt() to throw UnsupportedOperationException. This InputStream adapter only loads exactly the bytes a read requires (never prefetching), but Kryo's canReadInt() would have to look ahead at the next class-id byte, which is impossible without consuming it.
Source
Thrown at flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/NoFetchingInput.java:45
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@Internal
public class NoFetchingInput extends Input {
public NoFetchingInput(InputStream inputStream) {
super(inputStream, 8);
}
@Override
public int read() throws KryoException {
require(1);
return buffer[position++] & 0xFF;
}
@Override
public boolean canReadInt() throws KryoException {
throw new UnsupportedOperationException("NoFetchingInput cannot prefetch data.");
}
@Override
public boolean canReadLong() throws KryoException {
throw new UnsupportedOperationException("NoFetchingInput cannot prefetch data.");
}
/**
* Require makes sure that at least required number of bytes are kept in the buffer. If not,
* then it will load exactly the difference between required and currently available number of
* bytes. Thus, it will only load the data which is required and never prefetch data.
*
* @param required the number of bytes being available in the buffer
* @return The number of bytes remaining in the buffer, which will be at least <code>required
* </code> bytes.
* @throws KryoException
*/
@OverrideView on GitHub (pinned to 2f3c205e92)
Solutions
- Remove the custom ClassResolver or rewrite it so it does not call canReadInt()
- Replace canReadInt()-based optional-field logic in custom serializers with explicit version bytes you write/read yourself
- Test the full serialization round-trip under Flink's NoFetchingInput, not just plain Kryo Input
Example fix
// before (custom serializer)
if (input.canReadInt()) {
obj.setOptional(input.readInt());
}
// after (explicit flag)
boolean hasOptional = input.readByte() == 1;
if (hasOptional) {
obj.setOptional(input.readInt());
} Defensive patterns
Strategy: try-catch
Try / catch
try {
kryo.readObject(input, type);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("NoFetchingInput")) {
throw new IllegalStateException("Custom Kryo code uses canReadInt(); not supported under Flink runtime", e);
}
throw e;
} Prevention
- Never call canReadInt()/canReadLong() in custom Serializers or ClassResolvers used with Flink
- Encode optional data with explicit flags instead of stream probing
- Test custom Kryo serializers inside a Flink job, not only standalone Kryo
When it happens
Trigger: A Kryo ClassResolver or Serializer implementation calls input.canReadInt() while deserializing through Flink's DataInputView-based KryoDeserializer paths - e.g. custom ClassResolver implementations (like certain version-resolving resolvers) or serializers that peek the next registration id.
Common situations: User registers a custom Kryo ClassResolver (kryo.setClassResolver(...)) that uses canReadInt() to detect optional trailing class ids; upgrading Kryo version changes internal call patterns; custom serializers copied from Kryo examples that call canReadInt/canReadLong for optional fields.
Related errors
- Failed to serialize value '{value}'
- Cannot register null class or serializer.
- This object is a dummy TypeSerializer.
- Could not instantiate record
- Could not copy object by serializing/deserializing it.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/a6b34548830d5063.
Report an issue: GitHub.