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
- Serialize the full SpanContext with the library's toBytes() and pass the resulting array untouched
- Check the byte array length before calling parseBytes
- 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
- Round-trip contexts only via toBytes() output
- Check header/carrier size limits that may drop propagation bytes
- Log byte array length when propagation fails to spot truncation sources
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
- Unsupported version.
- Invalid input: expected trace ID at offset ${pos}
- Invalid input: expected span ID at offset ${pos}
- No ALTS context information found
- Can't set TLS settings for ALTS
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/ac59ec5bd8f84005.
Report an issue: GitHub.