gastownhall/beads · error
timestamp %q: %w
Error message
timestamp %q: %w
What it means
parseTime successfully parsed a timestamp string with one of the supported layouts (RFC3339Nano or SQLite-style datetime formats), but canonicalizing it to the current DATETIME representation failed. The original string is included in the message and the underlying cause (from canonicalCurrentDatetime) is wrapped with %w, so this error typically indicates a timestamp that parses but is unrepresentable (see the wrapped year-range error).
Source
Thrown at internal/migration/legacysqlite/reader.go:783
for _, v := range values {
if v.Valid && v.String != "" {
return true
}
}
return false
}
func nullString(v sql.NullString) string {
if v.Valid {
return v.String
}
return ""
}
func parseTime(s string) (time.Time, error) {
for _, layout := range []string{time.RFC3339Nano, "2006-01-02 15:04:05.999999999-07:00", "2006-01-02 15:04:05.999999999"} {
if t, e := time.Parse(layout, s); e == nil {
canonical, err := canonicalCurrentDatetime(t)
if err != nil {
return time.Time{}, fmt.Errorf("timestamp %q: %w", s, err)
}
return canonical, nil
}
}
return time.Time{}, fmt.Errorf("invalid timestamp %q", s)
}
func canonicalCurrentDatetime(t time.Time) (time.Time, error) {
canonical := t.UTC().Round(time.Second)
if year := canonical.Year(); year < 0 || year > 9999 {
return time.Time{}, fmt.Errorf("timestamp rounds outside current DATETIME range")
}
return canonical, nil
}
func parseOptionalTime(name string, raw sql.NullString) (*time.Time, error) {
if !raw.Valid {
return nil, nilView on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped cause in the message chain to see why canonicalization failed (usually year out of range).
- Fix the offending timestamp in the legacy SQLite DB to a realistic date before migrating (e.g. UPDATE dependencies SET created_at = ...).
- Ensure timestamps are written in RFC3339 or '2006-01-02 15:04:05' format with years 0001-9999.
- If seconds rounding pushes the value out of range (e.g. 9999-12-31T23:59:59.9), nudge the value back slightly.
Example fix
// before: created_at = '10000-01-01 00:00:00' UPDATE dependencies SET created_at = '2024-01-01 00:00:00' WHERE created_at = '10000-01-01 00:00:00'; // after: canonicalizable timestamp
Defensive patterns
Strategy: validation
Validate before calling
func timestampCanonicalizable(s string) bool {
for _, layout := range []string{time.RFC3339Nano, "2006-01-02 15:04:05.999999999-07:00", "2006-01-02 15:04:05.999999999"} {
if t, err := time.Parse(layout, s); err == nil {
y := t.UTC().Round(time.Second).Year()
return y >= 0 && y <= 9999
}
}
return false
} Type guard
func isStorableDatetime(t time.Time) bool {
y := t.UTC().Round(time.Second).Year()
return y >= 0 && y <= 9999
} Try / catch
// Go: wrap the migration call and inspect the wrapped cause
if err := migrateLegacy(db); err != nil {
var inner error
if errors.As(err, &inner) || strings.Contains(err.Error(), "timestamp") {
log.Fatalf("fix timestamp in legacy DB: %v", err)
}
return err
} Prevention
- Store all legacy timestamps in RFC3339 with years 0001-9999.
- Pre-parse every datetime column with the accepted layouts before running migration.
- Avoid far-future sentinel dates near the year-9999 boundary.
When it happens
Trigger: A dependency row's created_at or a comment/issue timestamp parses under one of the three accepted layouts, but t.UTC().Round(time.Second) yields a year outside 0..9999 (or another canonicalization failure). Raised from parseTime for callers parseOptionalTime, appendLegacyDependencyRow, and loadComments.
Common situations: Timestamps with extreme years (e.g. year 10000+) written by buggy tools; hand-edited SQLite rows with nonsense datetimes; dates far in the future like 9999-12-31T23:59:60 that round up past the representable range.
Related errors
- invalid timestamp %q
- timestamp rounds outside current DATETIME range
- %s: %w
- dependency created_at is zero for %s -> %s
- comment created_at is zero for issue %s
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/a981149c8a3851f0.
Report an issue: GitHub.