apache/druid · error · RE
Failed to deserialize RowSignature
Error message
Failed to deserialize RowSignature
What it means
FrameWireTransferable.deserializeFrame reads an optional serialized RowSignature from the frame's wire bytes and deserializes it with Jackson. A corrupt, truncated, or incompatible signature blob causes an IOException, rethrown as RE('Failed to deserialize RowSignature'). It indicates the binary frame payload is malformed or from an incompatible writer.
Solutions
- Verify the frame bytes are complete and not truncated in transit; check the serialization/deserialization code paths for offset bugs
- Align Druid versions between the producing and consuming nodes
- Capture the underlying IOException (it is the cause of the RE) to identify exact Jackson failure and fix the payload
- Re-generate/re-run the query that produced the frame rather than retrying the bad payload
Example fix
// before
Frame frame = FrameWireTransferable.deserializeFrame(bytes, mapper); // bytes truncated
// after
ByteBuffer buf = bytes.duplicate();
if (buf.remaining() < expectedHeaderSize) {
throw new IllegalStateException("Frame truncated: " + buf.remaining());
}
Frame frame = FrameWireTransferable.deserializeFrame(bytes, mapper); Defensive patterns
Strategy: try-catch
Validate before calling
if (bytes.remaining() < MIN_FRAME_HEADER) { throw new IllegalStateException("frame truncated"); } Type guard
null
Try / catch
try { deserializeFrame(bytes, mapper); } catch (RE e) { log.error("RowSignature deserialize failed; cause={}", e.getCause()); /* regenerate or reject frame */ } Prevention
- Inspect the IOException cause for exact failure
- Keep producing/consuming Druid versions aligned
- Checksum frames in custom transports to catch truncation
When it happens
Trigger: Deserializing a frame whose signature byte section is corrupt/truncated, written by an incompatible Druid version, or whose buffer offsets (signature length/bytes) were miscomputed.
Common situations: Network/channel corruption between clusters or across native-query/MSQ data exchange; version skew where the wire format changed; manually sliced or re-serialized frames in custom transport code.
Understand the failure class
Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.
Related errors
- Fail to decode protobuf message!
- Cannot add / to a Spectator Histogram
- Cannot create type [ ]
- Cannot deserialize type
- Cannot handle column
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/e5cfc78a88db6f4d.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/frame/wire/FrameWireTransferable.java:129
final int typeCodeLen = 0xFF & theBytes.get();
theBytes.position(theBytes.position() + typeCodeLen);
// Read flags.
final byte flags = theBytes.get();
final boolean hasSignature = (flags & HAS_SIGNATURE) != 0;
final RowSignature signature;
if (hasSignature) {
// Read signature.
final int signatureLen = theBytes.getInt();
final byte[] signatureBytes = new byte[signatureLen];
theBytes.get(signatureBytes);
try {
signature = mapper.readValue(signatureBytes, RowSignature.class);
}
catch (IOException e) {
throw new RE(e, "Failed to deserialize RowSignature");
}
} else {
signature = null;
}
// Read remaining bytes as a Frame.
final Frame frame = Frame.wrap(Memory.wrap(theBytes, ByteOrder.LITTLE_ENDIAN)
.region(theBytes.position(), theBytes.remaining()));
if (frame.type().isRowBased()) {
return new RowBasedFrameRowsAndColumns(frame, signature);
} else {
return new ColumnBasedFrameRowsAndColumns(frame, signature);
}
}
/**
* Deserializer for frames.View on GitHub (pinned to 9b90983fd2)