VictoriaMetrics/VictoriaMetrics · error
cannot find whitespace between metric and timestamp in %q
Error message
cannot find whitespace between metric and timestamp in %q
What it means
After stripping the 'put ' prefix, Row.unmarshal expects a whitespace separating the metric name from the timestamp. If no space is found, this error is returned with the offending string. The line is structurally invalid for the OpenTSDB put protocol.
Source
Thrown at lib/protoparser/opentsdb/parser.go:68
func (r *Row) reset() {
r.Metric = ""
r.Tags = nil
r.Value = 0
r.Timestamp = 0
}
func (r *Row) unmarshal(s string, tagsPool []Tag) ([]Tag, error) {
r.reset()
s = trimLeadingSpaces(s)
if !strings.HasPrefix(s, "put ") {
return tagsPool, fmt.Errorf("missing `put ` prefix in %q", s)
}
s = s[len("put "):]
s = trimLeadingSpaces(s)
n := strings.IndexByte(s, ' ')
if n < 0 {
return tagsPool, fmt.Errorf("cannot find whitespace between metric and timestamp in %q", s)
}
r.Metric = s[:n]
if len(r.Metric) == 0 {
return tagsPool, fmt.Errorf("metric cannot be empty")
}
tail := trimLeadingSpaces(s[n+1:])
n = strings.IndexByte(tail, ' ')
if n < 0 {
return tagsPool, fmt.Errorf("cannot find whitespace between timestamp and value in %q", s)
}
timestamp, err := fastfloat.Parse(tail[:n])
if err != nil {
return tagsPool, fmt.Errorf("cannot parse timestamp from %q: %w", tail[:n], err)
}
r.Timestamp = int64(timestamp)
tail = trimLeadingSpaces(tail[n+1:])
valueStr := ""
tagsStr := ""View on GitHub (pinned to 5079fb58f1)
Solutions
- Format each line as 'put <metric> <timestamp> <value> <tags>' with plain ASCII spaces.
- Check for tab-separated output from the producing script and convert to spaces.
- Log/print the offending line (shown in the error) and fix its formatting.
- Validate lines with a regex before sending: ^put \S+ \d+ \S+.*$.
Example fix
// before
fmt.Printf("put %s\t%d\t%v\n", metric, ts, val)
// after
fmt.Printf("put %s %d %v\n", metric, ts, val) Defensive patterns
Strategy: validation
Validate before calling
// ensure space-separated fields before sending
fields := strings.Fields(line)
if len(fields) < 4 {
return fmt.Errorf("opentsdb line needs >=4 fields: %q", line)
} Try / catch
if err := parser.Parse(body, cb); err != nil {
if strings.Contains(err.Error(), "cannot find whitespace between metric and timestamp") {
// offending line is quoted in the error
}
} Prevention
- Use single ASCII spaces between all fields
- Convert tab-separated output to spaces
- Validate with strings.Fields count == expected
When it happens
Trigger: Sending a put line like 'put mymetric\t...' with a non-space separator that survives trimming, or 'put mymetric' with no fields at all.
Common situations: Using tabs or multiple-space formatting that leaves IndexByte(' ') failing after trimming; truncated lines from broken scripts or cut-and-paste; locale-related separators.
Related errors
- cannot find whitespace between timestamp and value in %q
- missing `put ` prefix in %q
- metric cannot be empty
- cannot parse timestamp from %q: %w
- cannot parse value from %q: %w
AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03).
Data as JSON: /api/errors/762db347995317e4.
Report an issue: GitHub.