matryer/xbar · warning
bad interval unit: %s
Error message
bad interval unit: %s
What it means
validateRefreshInterval checks Unit against the fixed list days, hours, minutes, seconds, milliseconds and returns errors.Errorf("bad interval unit: %s") for anything else. SetRefreshInterval wraps it as 'invalid refresh interval'. The library only supports these five units because they map to xbar filename interval suffixes (d/h/m/s/ms).
Source
Thrown at pkg/plugins/refresh_interval.go:108
}
newVarFilename := newFilename + variableJSONFileExt
newVarFullPath := filepath.Join(pluginDirectory, newVarFilename)
if err := os.Rename(oldVarFullPath, newVarFullPath); err != nil {
return "", RefreshInterval{}, errors.Wrap(err, "rename plugin vars file to new refresh interval")
}
return newFilename, refreshInterval, nil
}
func validateRefreshInterval(refreshInterval RefreshInterval) error {
if n := refreshInterval.N; n < 1 {
return errors.Errorf("bad interval value: %d", n)
}
for _, unit := range []string{"days", "hours", "minutes", "seconds", "milliseconds"} {
if refreshInterval.Unit == unit {
return nil
}
}
return errors.Errorf("bad interval unit: %s", refreshInterval.Unit)
}
// ParseFilenameInterval parses the filename to extract the refresh interval
// or returns a default if it is do so.
func ParseFilenameInterval(filename string) (RefreshInterval, error) {
// ignore disabled piece
filename = strings.TrimSuffix(filename, disabledPluginExtension)
intervalStr := findIntervalInFilename(filename)
if intervalStr == "" {
return defaultRefreshInterval, nil
}
interval, err := parseInterval(intervalStr)
if err != nil {
return defaultRefreshInterval, errors.Errorf("%s (from %s)", err.Error(), filename)
}
return interval, nil
}
View on GitHub (pinned to d624239058)
Solutions
- Use exactly one of "days", "hours", "minutes", "seconds", "milliseconds" for Unit
- Normalize/sanitize user input (lowercase, map synonyms like "week" -> {N:7, Unit:"days"}) before constructing RefreshInterval
- Pre-construct intervals only from known constants rather than raw strings
Example fix
// before
_, _, err := plugins.SetRefreshInterval(dir, path, plugins.RefreshInterval{N: 1, Unit: "Week"})
// after
unit := strings.ToLower(unitInput)
if unit == "week" {
unit = "days"
n *= 7
}
_, _, err = plugins.SetRefreshInterval(dir, path, plugins.RefreshInterval{N: n, Unit: unit}) Defensive patterns
Strategy: validation
Validate before calling
var validUnits = map[string]bool{
"days": true, "hours": true, "minutes": true,
"seconds": true, "milliseconds": true,
}
func validUnit(u string) bool { return validUnits[strings.ToLower(u)] } Try / catch
if !validUnit(iv.Unit) {
return fmt.Errorf("unit %q not supported; use days|hours|minutes|seconds|milliseconds", iv.Unit)
}
_, _, err := plugins.SetRefreshInterval(dir, path, iv) Prevention
- Only build RefreshInterval from the five exact lowercase unit strings
- Normalize user input with strings.ToLower and map synonyms (week->7 days, min->minutes)
- Never derive Unit from time.Duration.String() output
When it happens
Trigger: Calling plugins.SetRefreshInterval with RefreshInterval{Unit: "week"}, "Minutes", "", or any casing/typo outside the exact five lowercase unit strings.
Common situations: Hand-written config using "weeks" or "days" with wrong casing; JSON deserialization of a user-supplied unit; translating a Go time.Duration string ("5m0s") into Unit; a UI locale differences.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
AI-assisted analysis of matryer/xbar@d624239058 (2026-09-02).
Data as JSON: /api/errors/05d86a2c97729d7d.
Report an issue: GitHub.