XTLS/Xray-core · error
invalid duration: %v
Error message
invalid duration: %v
What it means
Duration.UnmarshalJSON accepts only a JSON string parseable by time.ParseDuration (e.g. "300ms", "1m30s"). The default branch fires when the JSON value is any other type — a bare number, boolean, null, array, or object — and reports the received Go value with %v.
Source
Thrown at infra/conf/cfgcommon/duration/duration.go:33
}
// UnmarshalJSON implements encoding/json.Unmarshaler.UnmarshalJSON
func (d *Duration) UnmarshalJSON(b []byte) error {
var v interface{}
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch value := v.(type) {
case string:
var err error
dr, err := time.ParseDuration(value)
if err != nil {
return err
}
*d = Duration(dr)
return nil
default:
return fmt.Errorf("invalid duration: %v", v)
}
}
View on GitHub (pinned to 7d214f8b09)
Solutions
- Find the field named in the surrounding parse error and quote its value as a duration string with an explicit unit
- Use supported units: ns, us/µs, ms, s, m, h (composable, e.g. "1m30s")
- Do not use bare numbers — "5" alone is invalid even quoted
- Lint JSON configs for numeric values in known duration fields before deploy
Example fix
// before
"healthCheck": { "interval": 5, "idleTimeout": 300 }
// after
"healthCheck": { "interval": "5s", "idleTimeout": "300s" } Defensive patterns
Strategy: type-guard
Type guard
// JSON Schema-style guard for duration fields: must be a string with a unit
const durationRe = /^\d+(ns|us|µs|ms|s|m|h)+$/;
function isDurationString(v) {
return typeof v === "string" && durationRe.test(v);
}
// assert isDurationString(cfg.healthCheck.interval) before writing config Prevention
- Always quote durations with explicit units ("5s", "1m30s")
- Never emit bare numbers for duration fields from generators
- Add a JSON schema check for known duration keys in CI
When it happens
Trigger: Writing "idleTimeout": 300 or "interval": 5 instead of "300s"/"5m" anywhere a cfgcommon.Duration field is configured (health checks, policy buffer sizes/timeouts, transport keep-alive intervals, etc.).
Common situations: Muscle memory from configs where numeric seconds are accepted; JSON generators emitting numbers; migrating configs from tools that allow bare integers for durations.
Related errors
- failed to parse HTTP user
- failed to parse HTTP account
- failed to decode config:
- illegal ip rule:
- illegal domain rule:
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/9aaac545d308d582.
Report an issue: GitHub.