grpc/grpc-java · error · IllegalArgumentException
Invalid input: expected trace ID at offset ${pos}
Error message
Invalid input: expected trace ID at offset ${pos} What it means
BinaryFormat.parseBytes deserializes a SpanContext from the OpenTelemetry binary propagation format, which expects a version byte followed by the trace-ID field (field ID 0) with 16 bytes. This IllegalArgumentException is thrown when the byte at the trace-ID position is not the expected TRACE_ID_FIELD_ID, meaning the serialized bytes do not conform to the expected propagation format.
Source
Thrown at opentelemetry/src/main/java/io/grpc/opentelemetry/BinaryFormat.java:126
@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);
}
if (serialized.length > pos && serialized[pos] == TRACE_FLAG_FIELD_ID) {
if (serialized.length < ALL_FORMAT_LENGTH) {
throw new IllegalArgumentException("Invalid input: truncated");
}
traceFlags = TraceFlags.fromByte(serialized[pos + ID_SIZE]);
}
return SpanContext.create(traceId, spanId, traceFlags, TraceState.getDefault());
}
}
View on GitHub (pinned to 64daddc1f3)
Solutions
- Verify the incoming bytes were produced by the same OpenTelemetry binary format (version byte 0x00, then field ID 0x00 + 16-byte trace ID, then field ID 0x01 + 8-byte span ID, then optional trace-flags field).
- Check that the upstream service uses the OpenTelemetry binary propagator, not B3 or another format; align propagators on both sides.
- Inspect the raw bytes (hex dump) at offset 1 to confirm the field ID and that the array is at least 29 bytes long.
- Wrap parseBytes in try-catch for IllegalArgumentException and fall back to treating the header as absent (no valid span context).
Example fix
// before
SpanContext ctx = BinaryFormat.parseBytes(headerBytes);
// after
SpanContext ctx;
try {
ctx = BinaryFormat.parseBytes(headerBytes);
} catch (IllegalArgumentException e) {
ctx = SpanContext.getInvalid();
} Defensive patterns
Strategy: try-catch
Validate before calling
boolean isPlausibleOtelBinary(byte[] b) {
return b != null && b.length >= 1 && b[0] == 0 && b.length >= 29 && b[1] == 0;
} Try / catch
try {
ctx = BinaryFormat.parseBytes(bytes);
} catch (IllegalArgumentException e) {
ctx = SpanContext.getInvalid();
} Prevention
- Use the same OpenTelemetry propagator on both ends of the wire.
- Never hand-construct binary propagation bytes; always use the library's toByteArray.
- Hex-inspect unknown propagation values before parsing.
- Default to SpanContext.getInvalid() on parse failure so traces degrade gracefully.
When it happens
Trigger: Calling BinaryFormat.parseBytes (via the OpenTelemetry propagator's extract, e.g. SpanContext.fromByteArray or carrier extraction) with bytes whose second byte is not TRACE_ID_FIELD_ID (0x00) — i.e. a malformed, corrupted, or foreign-format binary span context.
Common situations: Interoperating with a service that emits a different binary propagation format (e.g. B3 binary or W3C traceparent encoded differently), bytes truncated to only the version byte, manual byte-array construction for tests, or an outdated/incompatible version of the propagator on the other side of the wire.
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
- Invalid input: expected span ID at offset ${pos}
- Unsupported version.
- Invalid input: truncated
- (message of wrapped InvalidProtocolBufferException)
- No ALTS context information found
AI-assisted analysis of grpc/grpc-java@64daddc1f3 (2026-09-08).
Data as JSON: /api/errors/1ae578bcc7a009e9.
Report an issue: GitHub.