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

  1. Normalize the timestamp offset to extended form '+HH:MM:SS' (or a standard 'Z' / '+03:00' that the conventional parser accepts) before parsing.
  2. Emit timestamps from the producer in RFC3339/ISO8601 standard form (e.g. time.Format(time.RFC3339)).
  3. 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

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


AI-assisted analysis of kataras/iris@7bedaf55a0 (2026-08-30). Data as JSON: /api/errors/0f858bb0a880f6f8. Report an issue: GitHub.