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

  1. Verify the frame bytes are complete and not truncated in transit; check the serialization/deserialization code paths for offset bugs
  2. Align Druid versions between the producing and consuming nodes
  3. Capture the underlying IOException (it is the cause of the RE) to identify exact Jackson failure and fix the payload
  4. 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

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


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)