grpc/grpc-go · error
transport: timeout string is too short: %q
Error message
transport: timeout string is too short: %q
What it means
This error occurs in decodeTimeout when the grpc-timeout HTTP/2 header value is shorter than 2 characters. The gRPC timeout format requires at least one digit followed by a unit character (e.g., '1S'), so a 0- or 1-character string cannot be parsed.
Source
Thrown at internal/transport/http_util.go:191
case minute:
return time.Minute, true
case second:
return time.Second, true
case millisecond:
return time.Millisecond, true
case microsecond:
return time.Microsecond, true
case nanosecond:
return time.Nanosecond, true
default:
}
return
}
func decodeTimeout(s string) (time.Duration, error) {
size := len(s)
if size < 2 {
return 0, fmt.Errorf("transport: timeout string is too short: %q", s)
}
if size > 9 {
// Spec allows for 8 digits plus the unit.
return 0, fmt.Errorf("transport: timeout string is too long: %q", s)
}
unit := timeoutUnit(s[size-1])
d, ok := timeoutUnitToDuration(unit)
if !ok {
return 0, fmt.Errorf("transport: timeout unit is not recognized: %q", s)
}
t, err := strconv.ParseUint(s[:size-1], 10, 64)
if err != nil {
return 0, err
}
const maxHours = math.MaxInt64 / uint64(time.Hour)
if d == time.Hour && t > maxHours {
// This timeout would overflow math.MaxInt64; clamp it.
return time.Duration(math.MaxInt64), nilView on GitHub (pinned to 03255a9237)
Solutions
- Inspect the grpc-timeout header on the offending request using network tracing (e.g., Wireshark with HTTP/2 dissection).
- Fix or upgrade the client/proxy that produces the truncated header.
- If you control the client, ensure context deadlines are set properly so grpc-timeout is well-formed.
Example fix
// before (broken): empty or single-char timeout header sent by client
metadata: {"grpc-timeout": ""}
// after (valid): client sets a proper deadline
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
// grpc-go encodes this as "5000m" (5 seconds in millis) Defensive patterns
Strategy: validation
Validate before calling
// Validate a grpc-timeout header value before processing
func validateGrpcTimeout(s string) error {
if len(s) < 2 {
return fmt.Errorf("timeout too short: needs >=1 digit + unit")
}
return nil
} Try / catch
// On the server side, malformed grpc-timeout results in a stream abort
// with codes.Internal. Handle gracefully:
if status.Code(err) == codes.Internal {
if strings.Contains(err.Error(), "malformed grpc-timeout") {
log.Printf("client sent invalid timeout header")
}
} Prevention
- Always set context deadlines on the client side so grpc-timeout is well-formed.
- Use a compliant gRPC client library to ensure proper header encoding.
- Monitor for protocol-level rejections in server logs to detect buggy clients.
When it happens
Trigger: An incoming gRPC request (or the client side decoding a server-sent timeout) has a grpc-timeout header with fewer than 2 bytes. This is typically caused by a malformed peer or an intermediary (proxy/LB) corrupting the header.
Common situations: A non-gRPC client or buggy proxy sends an empty or truncated grpc-timeout header; interoperability issues with an HTTP/2 implementation that strips the header value; or a load balancer that mangles header values.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- transport: timeout string is too long: %q
- transport: timeout unit is not recognized: %q
- keepalive ping not acked within timeout %s
- received %d-bytes data exceeding the limit %d bytes
- received an illegal stream id: %v. headers frame: %+v
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/92cf394d7314dca4.
Report an issue: GitHub.