grpc/grpc-go · error
transport: timeout string is too long
Error message
transport: timeout string is too long: %q
What it means
Fires in decodeTimeout (http_util.go:195) when the grpc-timeout header value is longer than 9 characters. The gRPC spec allows at most 8 decimal digits plus a single unit character, to bound the encoded size; longer values are rejected as malformed even if they would otherwise parse.
Solutions
- Shorten the grpc-timeout value to <= 8 digits plus a unit (choose a larger unit if needed, e.g. "99999999S" is fine but "999999999S" is not).
- Prefer letting gRPC encode the deadline from context.WithTimeout rather than setting grpc-timeout manually.
- Audit proxies/LBs for header rewriting that appends or pads characters.
Example fix
// before: manual header with too many digits
// metadata: {"grpc-timeout": "1000000000S"} // 10 digits -> too long
// after
ctx, cancel := context.WithTimeout(ctx, 1000*time.Second)
defer cancel()
client.Method(ctx, req) // gRPC emits a spec-compliant value Defensive patterns
Strategy: validation
Validate before calling
func validTimeoutHeaderLen(s string) bool {
return len(s) >= 2 && len(s) <= 9 // digits + unit
} Prevention
- Keep grpc-timeout to <= 8 digits plus a unit.
- Use gRPC's deadline propagation instead of manual headers.
- Pick a larger unit when the value has many digits.
When it happens
Trigger: An inbound grpc-timeout value of length > 9. Examples: a caller formatting the timeout with more than 8 significant digits ("123456789S"), padding with leading zeros ("0000000010S"), or appending extra characters; a proxy that mangles the header; a non-conformant client.
Common situations: A custom client/proxy that builds the header without honoring the 8-digit limit; values derived from nanosecond timestamps expressed in hours (huge digit counts); header corruption by a middlebox.
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 short
- transport: timeout unit is not recognized
- received an illegal stream id
- received -bytes data exceeding the limit bytes
- ErrCodeEnhanceYourCalm
AI-assisted analysis of grpc/grpc-go@0c51461d27 (2026-08-11).
Data as JSON: /api/errors/b5322968218b0bf0.
Report an issue: GitHub.
Appendix: source
Thrown at internal/transport/http_util.go:195
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), nil
}
return d * time.Duration(t), nil
}
View on GitHub (pinned to 0c51461d27)