VictoriaMetrics/VictoriaMetrics · error
cannot parse minute from timezone offset %q: %w
Error message
cannot parse minute from timezone offset %q: %w
What it means
Fires in ParseTimeAt when the trailing timezone offset of a timestamp string (the last 6 characters, e.g. +05:30) has a sign and colon but its minute part (characters after the colon) is not a valid unsigned integer. ParseTimeAt cannot apply the offset, so the whole timestamp fails to parse.
Source
Thrown at lib/timeutil/time.go:50
// It returns unix timestamp in nanoseconds.
func ParseTimeAt(s string, currentTimestamp int64) (int64, error) {
if s == "now" {
return currentTimestamp, nil
}
sOrig := s
tzOffset := int64(0)
if len(sOrig) > 6 {
// Try parsing timezone offset
tz := sOrig[len(sOrig)-6:]
if (tz[0] == '-' || tz[0] == '+') && tz[3] == ':' {
isPlus := tz[0] == '+'
hour, err := strconv.ParseUint(tz[1:3], 10, 64)
if err != nil {
return 0, fmt.Errorf("cannot parse hour from timezone offset %q: %w", tz, err)
}
minute, err := strconv.ParseUint(tz[4:], 10, 64)
if err != nil {
return 0, fmt.Errorf("cannot parse minute from timezone offset %q: %w", tz, err)
}
tzOffset = int64(hour*3600+minute*60) * 1e9
if isPlus {
tzOffset = -tzOffset
}
s = sOrig[:len(sOrig)-6]
} else {
if !strings.HasSuffix(s, "Z") {
tzOffset = -GetLocalTimezoneOffsetNsecs()
} else {
s = s[:len(s)-1]
}
}
}
s = strings.TrimSuffix(s, "Z")
if len(s) > 0 && (s[len(s)-1] > '9' || s[0] == '-') || strings.HasPrefix(s, "now") {
// Parse duration relative to the current time
s = strings.TrimPrefix(s, "now")View on GitHub (pinned to 5079fb58f1)
Solutions
- Supply a complete RFC3339 offset, e.g. `2024-01-02T10:00:00+02:30`
- Fix the upstream producer that emits placeholder minutes
- Parse the timestamp yourself (time.Parse with the right layout) if inputs are nonstandard
Example fix
// before
ParseTimeAt("2024-01-02T10:00:00+02:MM", nil)
// after
ParseTimeAt("2024-01-02T10:00:00+02:30", nil) Defensive patterns
Strategy: validation
Validate before calling
var tzRe = regexp.MustCompile(`[+-]([0-9]{2}):([0-9]{2})$`)
func validOffsetMinutes(s string) bool {
m := tzRe.FindStringSubmatch(s)
if m == nil {
return false
}
_, err1 := strconv.ParseUint(m[1], 10, 64)
_, err2 := strconv.ParseUint(m[2], 10, 64)
return err1 == nil && err2 == nil
} Type guard
func hasRFC3339Offset(s string) bool {
_, err := time.Parse(time.RFC3339, s)
return err == nil
} Try / catch
ts, err := timeutil.ParseTimeMsec(s, nil)
if err != nil {
log.Printf("skipping malformed timestamp %q: %v", s, err)
} Prevention
- Validate RFC3339 format upstream before calling ParseTimeAt/ParseTimeMsec
- Expand `+HH:MM` placeholders in templates and fail fast if unsubstituted
When it happens
Trigger: ParseTimeAt / ParseTimeMsec with timestamps like `"2024-01-02T10:00:00+02:MM"` or `"...+02:--"` — the last 6 chars look like an offset but tz[4:] is not a valid digit string.
Common situations: Corrupted log timestamps; placeholders like `+HH:MM` never substituted with real digits; truncation/encoding issues mangling the tail of an RFC3339 string.
Related errors
- cannot parse hour from timezone offset %q: %w
- duration %q must be in the range [%s, %s]
- unexpected number of items in authToken %q; got %d; want 1 o
- cannot parse accountID from %q: %w
- cannot parse projectID from %q: %w
AI-assisted analysis of VictoriaMetrics/VictoriaMetrics@5079fb58f1 (2026-09-03).
Data as JSON: /api/errors/8564f04a4c7735e4.
Report an issue: GitHub.