gastownhall/beads · error
invalid closed time: %w
Error message
invalid closed time: %w
What it means
Wraps a parseTimeValue failure for the closed field: the value of a `closed` comparison could not be parsed as a relative time or absolute timestamp. The raw parser error is preserved with %w. Note that closed filters only make sense for issues that have been closed; parsing happens before any operator dispatch.
Source
Thrown at internal/query/evaluator.go:388
case OpGreater:
filter.UpdatedAfter = &t
case OpGreaterEq:
filter.UpdatedAfter = &t
case OpLess:
filter.UpdatedBefore = &t
case OpLessEq:
endOfDay := time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 999999999, t.Location())
filter.UpdatedBefore = &endOfDay
default:
return fmt.Errorf("updated does not support %s operator", comp.Op.String())
}
return nil
}
func (e *Evaluator) applyClosedFilter(comp *ComparisonNode, filter *types.IssueFilter) error {
t, err := e.parseTimeValue(comp)
if err != nil {
return fmt.Errorf("invalid closed time: %w", err)
}
switch comp.Op {
case OpGreater:
filter.ClosedAfter = &t
case OpGreaterEq:
filter.ClosedAfter = &t
case OpLess:
filter.ClosedBefore = &t
case OpLessEq:
endOfDay := time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 999999999, t.Location())
filter.ClosedBefore = &endOfDay
default:
return fmt.Errorf("closed does not support %s operator", comp.Op.String())
}
return nil
}
func (e *Evaluator) applyStartedFilter(comp *ComparisonNode, filter *types.IssueFilter) error {View on GitHub (pinned to 71377f2769)
Solutions
- Use a supported duration form: `closed > 30d`, `closed < 24h`
- Use an absolute date/time accepted by ParseRelativeTime (e.g. `2026-08-01` or RFC3339)
- Check the wrapped cause in the error chain to identify the exact parse problem
Example fix
// before bd list 'closed > one month ago' // after bd list 'closed > 30d'
Defensive patterns
Strategy: validation
Validate before calling
// Validate the closed value parses before running the query
func validClosedValue(v string) bool {
if regexp.MustCompile(`^\d+[dhmsw]$`).MatchString(v) {
return true
}
_, err := timeparsing.ParseRelativeTime(v, time.Now())
return err == nil
}
if !validClosedValue(value) { return fmt.Errorf("bad closed value: %q", value) } Type guard
func isParseableTime(v string) bool {
_, err := timeparsing.ParseRelativeTime(v, time.Now())
return err == nil
} Try / catch
if err := eval.Eval(node); err != nil {
if strings.Contains(err.Error(), "invalid closed time") {
// fix the value (e.g. 'one month ago' -> '30d') and retry
}
} Prevention
- Use compact durations for closed filters: 30d, 7d
- Use ISO dates for absolute cutoffs
- Never interpolate prose date phrases into queries
- Unwrap errors.As to the underlying parse error when debugging
When it happens
Trigger: Queries like `closed > 30x`, `closed < ''`, `closed >= nonsense` — any `closed <op> value` whose value fails duration (parseDurationAgo) or relative-time (ParseRelativeTime) parsing.
Common situations: Reporting scripts with malformed interpolated dates; units the duration parser rejects; users typing prose dates (`closed > last month`) where only compact forms work; running closed filters in environments where relative keywords differ.
Related errors
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/40f956ee81d533d2.
Report an issue: GitHub.