kataras/iris · error
invalid offset format: %s
Error message
invalid offset format: %s
What it means
ParseISO8601's adjustForUnconventionalOffset helper handles timezone offsets written as '+HH:MM:SS'. After stripping the sign it splits on ':' and requires exactly three numeric parts. This error is returned when the offset component of the timestamp does not contain three colon-separated fields, so the offset cannot be interpreted as hours:minutes:seconds.
Source
Thrown at x/jsonx/iso8601.go:232
return secondsEastUTC, nil
}
func isUnconventionalOffset(offset string) bool {
parts := strings.Split(offset, ":")
return len(parts) == 3
}
func adjustForUnconventionalOffset(t time.Time, offset string) (time.Time, error) {
sign := 1
if offset[0] == '-' {
sign = -1
}
offset = offset[1:]
offsetParts := strings.Split(offset, ":")
if len(offsetParts) != 3 {
return time.Time{}, fmt.Errorf("invalid offset format: %s", offset)
}
hours, err := strconv.Atoi(offsetParts[0])
if err != nil {
return time.Time{}, fmt.Errorf("error parsing offset hours: %s: %w", offset, err)
}
if hours > 24 {
return time.Time{}, fmt.Errorf("invalid offset hours: %d: %s", hours, offset)
}
minutes, err := strconv.Atoi(offsetParts[1])
if err != nil {
return time.Time{}, fmt.Errorf("error parsing offset minutes: %s: %w", offset, err)
}
if minutes > 60 {
return time.Time{}, fmt.Errorf("invalid offset minutes: %d: %s", minutes, offset)
}View on GitHub (pinned to 7bedaf55a0)
Solutions
- Normalize the timestamp offset to extended form '+HH:MM:SS' (or a standard 'Z' / '+03:00' that the conventional parser accepts) before parsing.
- Emit timestamps from the producer in RFC3339/ISO8601 standard form (e.g. time.Format(time.RFC3339)).
- Sanitize at the boundary: convert '+0300' to '+03:00' with a small regex/string transform before calling ParseISO8601.
Example fix
// before
ParseISO8601("2024-01-02T15:04:05+0300") // invalid offset format
// after
ParseISO8601("2024-01-02T15:04:05+03:00") Defensive patterns
Strategy: validation
Validate before calling
var offsetRe = regexp.MustCompile(`^[+-]\d{1,2}:\d{2}:\d{2}$`)
func hasValidOffset(ts string) bool {
i := strings.LastIndexAny(ts, "+-")
return i >= 0 && offsetRe.MatchString(ts[i:])
} Type guard
func isStandardRFC3339(s string) bool {
_, err := time.Parse(time.RFC3339, s)
return err == nil
} Prevention
- Always emit timestamps with time.Format(time.RFC3339) at the producer side.
- Normalize compact offsets (+0300) to extended form before parsing.
- Validate the offset component with a regex before calling ParseISO8601.
When it happens
Trigger: Calling ParseISO8601 (or ISO8601.UnmarshalJSON) with a timestamp whose UTC offset only becomes 'unconventional' during the split but lacks three parts — e.g. an offset like '+0300' or '+03' that reaches this code path with the wrong number of colon-delimited fields, or an empty offset string.
Common situations: Feeding timestamps from external systems that emit compact offsets (+0300) or hour-only offsets (+03); hand-crafted or copied date strings; upstream services changing timestamp serialization formats.
Related errors
- ISO8601: invalid timezone format: %s
- ISO8601: %w
- ISO8601: invalid timezone offset length: %s
- ISO8601: invalid timezone offset sign: %c
- error parsing offset hours: %s: %w
AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30).
Data as JSON: /api/errors/0f858bb0a880f6f8.
Report an issue: GitHub.