cloudflare/cloudflared · error
couldn't parse index from timeout hop: %w
Error message
couldn't parse index from timeout hop: %w
What it means
DecodeLine (Unix) parses traceroute output lines for timeout hops, expecting the first whitespace-separated field to be the hop index. When strconv.ParseUint cannot parse parts[0] as an integer, the line does not follow the expected traceroute format and this wrapped error is returned, failing network diagnostic decoding.
Source
Thrown at diagnostic/network/collector_unix.go:53
process := exec.CommandContext(ctx, command, args...)
return decodeNetworkOutputToFile(process, DecodeLine)
}
func DecodeLine(text string) (*Hop, error) {
fields := strings.Fields(text)
parts := []string{}
filter := func(s string) bool { return s != "*" && s != "ms" }
for _, field := range fields {
if filter(field) {
parts = append(parts, field)
}
}
index, err := strconv.ParseUint(parts[0], 10, 8)
if err != nil {
return nil, fmt.Errorf("couldn't parse index from timeout hop: %w", err)
}
if len(parts) == 1 {
return NewTimeoutHop(uint8(index)), nil
}
domain := ""
rtts := []time.Duration{}
for _, part := range parts[1:] {
rtt, err := strconv.ParseFloat(part, 64)
if err != nil {
domain += part + " "
} else {
rtts = append(rtts, time.Duration(rtt*MicrosecondsFactor))
}
}
View on GitHub (pinned to 2253eeeb25)
Solutions
- Ensure the standard iputils traceroute is installed and used (check which traceroute).
- Verify traceroute output manually for the target host and confirm hop lines parse as expected.
- Fix locale-related formatting (LC_ALL=C) if numeric output is localized.
- Handle the error in the caller by skipping/reporting unparseable lines rather than treating the whole diagnostic as fatal, if a traceroute variant must be tolerated.
Example fix
// before
hops, _, err := network.Collect(ctx, config)
if err != nil {
return err
}
// after
hops, _, err := network.Collect(ctx, config)
if err != nil {
var parseErr *strconv.NumError
if errors.As(err, &parseErr) {
// non-numeric hop index: incompatible traceroute output
log.Warn().Err(err).Msg("unexpected traceroute format")
}
return fmt.Errorf("network collect: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// pre-check the traceroute binary and a sample of its output format
out, err := exec.Command("traceroute", "--help").Output()
if err != nil {
// unsupported or missing traceroute
} Try / catch
hops, err := network.Collect(ctx, cfg)
var numErr *strconv.NumError
if errors.As(err, &numErr) {
// incompatible traceroute output: log raw tee output for debugging
} Prevention
- Install standard iputils traceroute on Linux hosts
- Run with LC_ALL=C to keep numeric output stable
- Inspect raw traceroute output when decoding fails
- Keep the diagnostic package updated for new traceroute variants
When it happens
Trigger: Decoding a traceroute line whose first token is not a number — e.g. a header line like 'traceroute to ...', warning lines, or output from a traceroute variant with a different column layout piped into Decode.
Common situations: Running an unsupported traceroute implementation (busybox, musl variants) whose output format differs; traceroute emits non-hop lines (DNS warnings, headers) that reach the timeout-hop branch; locale changes the output 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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- error starting traceroute: %w
- error finishing traceroute: %w
- scanner reported an error: %w
- couldn't parse index from timeout hop: %w
- ErrInsufficientLines
AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06).
Data as JSON: /api/errors/207dcc2c68a656f4.
Report an issue: GitHub.