grpc/grpc-java · warning · IllegalArgumentException

Invalid input: truncated

Error message

Invalid input: truncated

What it means

After checking the version byte, BinaryFormat.parseBytes requires the serialized SpanContext blob to be at least REQUIRED_FORMAT_LENGTH bytes long (version + trace-id + span-id + flags fields). Shorter input is rejected with IllegalArgumentException 'Invalid input: truncated'.

Source

Thrown at opentelemetry/src/main/java/io/grpc/opentelemetry/BinaryFormat.java:115

    bytes[VERSION_ID_OFFSET] = VERSION_ID;
    bytes[TRACE_ID_FIELD_ID_OFFSET] = TRACE_ID_FIELD_ID;
    System.arraycopy(spanContext.getTraceIdBytes(), 0, bytes, TRACE_ID_OFFSET, TRACE_ID_SIZE);
    bytes[SPAN_ID_FIELD_ID_OFFSET] = SPAN_ID_FIELD_ID;
    System.arraycopy(spanContext.getSpanIdBytes(), 0, bytes, SPAN_ID_OFFSET, SPAN_ID_SIZE);
    bytes[TRACE_FLAG_FIELD_ID_OFFSET] = TRACE_FLAG_FIELD_ID;
    bytes[TRACE_FLAG_OFFSET] = spanContext.getTraceFlags().asByte();
    return bytes;
  }


  @Override
  public SpanContext parseBytes(byte[] serialized) {
    checkNotNull(serialized, "bytes");
    if (serialized.length == 0 || serialized[0] != VERSION_ID) {
      throw new IllegalArgumentException("Unsupported version.");
    }
    if (serialized.length < REQUIRED_FORMAT_LENGTH) {
      throw new IllegalArgumentException("Invalid input: truncated");
    }
    String traceId;
    String spanId;
    TraceFlags traceFlags = TraceFlags.getDefault();
    int pos = 1;
    if (serialized[pos] == TRACE_ID_FIELD_ID) {
      traceId = TraceId.fromBytes(
          Arrays.copyOfRange(serialized, pos + ID_SIZE, pos + ID_SIZE + TRACE_ID_SIZE));
      pos += ID_SIZE + TRACE_ID_SIZE;
    } else {
      throw new IllegalArgumentException("Invalid input: expected trace ID at offset " + pos);
    }
    if (serialized[pos] == SPAN_ID_FIELD_ID) {
      spanId = SpanId.fromBytes(
          Arrays.copyOfRange(serialized, pos + ID_SIZE, pos + ID_SIZE + SPAN_ID_SIZE));
      pos += ID_SIZE + SPAN_ID_SIZE;
    } else {
      throw new IllegalArgumentException("Invalid input: expected span ID at offset " + pos);

View on GitHub (pinned to 64daddc1f3)

Solutions

  1. Serialize the full SpanContext with the library's toBytes() and pass the resulting array untouched
  2. Check the byte array length before calling parseBytes
  3. Verify no intermediary (proxy, header limit, custom carrier) is truncating the propagation payload

Example fix

// before
SpanContext ctx = propagator.parseBytes(shortBytes);
// after
if (shortBytes != null && shortBytes.length >= 29) { SpanContext ctx = propagator.parseBytes(shortBytes); }
Defensive patterns

Strategy: validation

Validate before calling

boolean isCompleteSpanContext(byte[] b) { return b != null && b.length >= 29 && b[0] == 0; }

Try / catch

try { ctx = propagator.parseBytes(bytes); }
catch (IllegalArgumentException e) {
  if ("Invalid input: truncated".equals(e.getMessage())) { /* treat as missing trace context */ ctx = SpanContext.INVALID; }
}

Prevention

When it happens

Trigger: Calling parseBytes with a byte array shorter than REQUIRED_FORMAT_LENGTH (but non-empty and version-correct) — e.g. a carrier written partially, truncated network payload, or wrong field bytes.

Common situations: Carrier maps truncated by intermediaries, hand-rolled serialization that omits trailing fields, binary/HTTP header propagation mix-ups dropping bytes.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08). Data as JSON: /api/errors/ac59ec5bd8f84005. Report an issue: GitHub.