kopia/kopia · error
invalid duration
Error message
invalid duration %s: %w
What it means
jsonencoding.Duration.UnmarshalText (jsonencoding.go:34) first tries to interpret the text as a plain float of nanoseconds; if that fails it falls back to time.ParseDuration. When both fail, the raw value is wrapped as "invalid duration %s". Any JSON/text field using this Duration type must contain a Go-style duration string or a number of nanoseconds.
Solutions
- Use Go duration syntax with units: "300ms", "1h30m", "24h", "720h" for 30 days.
- Or provide a plain number interpreted as nanoseconds (e.g. 5000000).
- Convert unsupported units manually (weeks→168h, days→24h) in the config.
- Pre-validate the string with time.ParseDuration before writing it into the config.
Example fix
// before
{"interval": "1 day"}
// after
{"interval": "24h"} Defensive patterns
Strategy: validation
Validate before calling
func parseDur(s string) error {
if _, err := time.ParseDuration(s); err != nil {
if _, ferr := strconv.ParseFloat(s, 64); ferr != nil {
return fmt.Errorf("invalid duration %q", s)
}
}
return nil
} Try / catch
if err := json.Unmarshal(data, &cfg); err != nil {
var durErr error
if strings.Contains(err.Error(), "invalid duration") {
return fmt.Errorf("check duration fields (use Go syntax like 24h): %w", err)
}
return err
} Prevention
- Write durations in Go syntax with units: 30s, 24h, 720h.
- Never use spaces or words like days/weeks in duration fields.
- Validate duration strings with time.ParseDuration before writing configs.
When it happens
Trigger: Unmarshaling JSON/YAML into jsonencoding.Duration with values like "1 hour", "1h30m", "5 mins", "daily", or "" — strings time.ParseDuration cannot parse (no unit, unsupported unit, embedded spaces).
Common situations: Hand-edited config files writing human-friendly durations ("30 days", "1 week"); cron-like strings; locale-formatted numbers with thousand separators; empty values.
Understand the failure class
Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.
Related errors
- error parsing JSON
- error parsing JSON
- error parsing storage config for bucket
- errors indenting JSON
- unexpected token (%T)
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/1a1151eec3107561.
Report an issue: GitHub.
Appendix: source
Thrown at repo/jsonencoding/jsonencoding.go:34
// MarshalText writes d as text.
func (d Duration) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
}
// UnmarshalText read d from a text representation.
func (d *Duration) UnmarshalText(b []byte) error {
s := string(bytes.TrimSpace(b))
f, err := strconv.ParseFloat(s, 64)
if err == nil {
d.Duration = time.Duration(f)
return nil
}
d.Duration, err = time.ParseDuration(s)
if err != nil {
return fmt.Errorf("invalid duration %s: %w", s, err)
}
return nil
}
View on GitHub (pinned to 82495e54b5)