kataras/iris · error

invalid duration format: expected hours:minutes:seconds (e.g

Error message

invalid duration format: expected hours:minutes:seconds (e.g. 01:05:00) but got: %s

What it means

ParseTimeNotationDuration splits the input on ':' and requires exactly three parts (hours:minutes:seconds). Strings with fewer than three colon-separated parts — e.g. "10:00", "90m", "" — fail immediately with "invalid duration format: expected hours:minutes:seconds (e.g. 01:05:00) but got: %s".

Source

Thrown at x/jsonx/time_notation.go:30

	"time"
)

// TimeNotationDuration is a JSON representation of the standard Duration type in 00:00:00 (hour, minute seconds).
type TimeNotationDuration time.Duration

func fmtDuration(d time.Duration) string {
	d = d.Round(time.Minute)
	h := d / time.Hour
	d -= h * time.Hour
	m := d / time.Minute
	return fmt.Sprintf("%02d:%02d:00", h, m) // Manos doesn't care about the seconds.
}

// ParseTimeNotationDuration parses a string to a time notation duration (00:00:00) hours:minutes:seconds.
func ParseTimeNotationDuration(s string) (TimeNotationDuration, error) {
	entries := strings.SplitN(s, ":", 3)
	if len(entries) < 3 {
		return TimeNotationDuration(0), fmt.Errorf("invalid duration format: expected hours:minutes:seconds (e.g. 01:05:00) but got: %s", s)
	}

	hours, err := strconv.Atoi(entries[0])
	if err != nil {
		return TimeNotationDuration(0), err
	}
	minutes, err := strconv.Atoi(entries[1])
	if err != nil {
		return TimeNotationDuration(0), err
	}

	// remove any .0000
	secondsStr := strings.TrimSuffix(entries[2], ".000000")
	seconds, err := strconv.Atoi(secondsStr)
	if err != nil {
		return TimeNotationDuration(0), err
	}

View on GitHub (pinned to 7bedaf55a0)

Solutions

  1. Pad the value to three parts before parsing: "10:00" -> "10:00:00".
  2. If the source is Go time.Duration text, convert with time.ParseDuration and TimeNotationDuration.Set instead.
  3. On Postgres, cast TIME columns with to_char(col, 'HH24:MI:SS') so three parts are always present.

Example fix

// before
jsonx.ParseTimeNotationDuration("10:00") // error
// after
jsonx.ParseTimeNotationDuration("10:00:00")
Defensive patterns

Strategy: validation

Validate before calling

func isTimeNotation(s string) bool {
	parts := strings.SplitN(s, ":", 3)
	if len(parts) != 3 { return false }
	for _, p := range parts {
		if _, err := strconv.Atoi(p); err != nil { return false }
	}
	return true
}

Type guard

func normalizeTimeNotation(s string) string {
	parts := strings.Split(s, ":")
	for len(parts) < 3 {
		parts = append(parts, "00")
	}
	return strings.Join(parts[:3], ":")
}

Try / catch

d, err := jsonx.ParseTimeNotationDuration(s)
if err != nil {
	if strings.HasPrefix(err.Error(), "invalid duration format") {
		d, err = jsonx.ParseTimeNotationDuration(normalizeTimeNotation(s))
	}
	if err != nil { return err }
}

Prevention

When it happens

Trigger: Calling jsonx.ParseTimeNotationDuration directly, or via TimeNotationDuration.UnmarshalJSON with a short string, or via KitchenTime.Scan receiving a string TIME value with only h:mm (two parts).

Common situations: DB TIME values rendered as "10:00" (HH:MM); user-supplied durations like "1:30" intended as 1h30m; config files storing Go duration strings ("1h30m").

Related errors


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