grpc/grpc-java · error · IllegalArgumentException
Invalid input: expected span ID at offset ${pos}
Error message
Invalid input: expected span ID at offset ${pos} What it means
After successfully parsing the trace ID, BinaryFormat.parseBytes expects the next byte to be the span-ID field ID (0x01) followed by an 8-byte span ID. This IllegalArgumentException is thrown when the byte at the current offset does not match SPAN_ID_FIELD_ID, indicating the serialized span context is not in the expected OpenTelemetry binary format.
Source
Thrown at opentelemetry/src/main/java/io/grpc/opentelemetry/BinaryFormat.java:133
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
- Ensure the writer serializes both trace ID (16 bytes) and span ID (8 bytes) fields with their field IDs in the OpenTelemetry binary format order.
- Check carrier/header size limits are not truncating the serialized span context before it reaches parseBytes.
- Validate byte-array length (at least 29 bytes for version + trace + span fields) before parsing.
- Catch IllegalArgumentException and fall back to an invalid/absent span context for graceful degradation.
Defensive patterns
Strategy: try-catch
Validate before calling
boolean hasSpanIdField(byte[] b) {
// version(1) + fieldId(1) + traceId(16) + fieldId(1) = offset 19 must hold SPAN_ID_FIELD_ID (0x01)
return b != null && b.length >= 20 && b[19] == 0x01;
} Try / catch
try {
ctx = BinaryFormat.parseBytes(bytes);
} catch (IllegalArgumentException e) {
log.warn("malformed span context", e);
ctx = SpanContext.getInvalid();
} Prevention
- Ensure senders serialize both trace and span ID fields in format order.
- Check metadata carrier size limits are not truncating propagation values.
- Keep propagator library versions aligned across services.
- Wrap parsing with a fallback to an invalid span context.
When it happens
Trigger: Calling parseBytes with bytes where the span-ID field is missing, reordered, or replaced — e.g. a truncated payload containing version + trace ID but no span-ID field, or bytes written by a non-conforming encoder.
Common situations: Hand-rolled propagation serializers that emit only the trace ID, a truncated header due to size-limited metadata carriers, or version skew between writer and reader implementations of the binary format.
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 trace 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/310ea6ad0b912b8c.
Report an issue: GitHub.