gastownhall/beads · error
legacy SQLite %s is %d characters (current VARCHAR(%d) maxim
Error message
legacy SQLite %s is %d characters (current VARCHAR(%d) maximum)
What it means
During legacy SQLite migration, a text field exceeds the current Dolt-backed VARCHAR column width (measured in runes, not bytes). The reader pre-validates every issue, label, dependency, and comment field against the current schema limits so the import fails loudly instead of being silently truncated or rejected by the target database. The error names the offending field, its rune count, and the allowed maximum.
Source
Thrown at internal/migration/legacysqlite/reader.go:744
{"issue event_kind", issue.EventKind, currentShortVarcharRunes},
{"issue actor", issue.Actor, types.MaxFieldLen},
{"issue target", issue.Target, types.MaxFieldLen},
{"issue work_type", string(issue.WorkType), currentShortVarcharRunes},
{"issue source_system", issue.SourceSystem, types.MaxFieldLen},
}
if issue.ExternalRef != nil {
fields = append(fields, currentVarchar{"issue external_ref", *issue.ExternalRef, types.MaxFieldLen})
}
if issue.CompactedAtCommit != nil {
fields = append(fields, currentVarchar{"issue compacted_at_commit", *issue.CompactedAtCommit, currentCommitVarcharRunes})
}
return checkCurrentVarchars(fields...)
}
func checkCurrentVarchars(fields ...currentVarchar) error {
for _, field := range fields {
if n := utf8.RuneCountInString(field.value); n > field.maxRunes {
return fmt.Errorf("legacy SQLite %s is %d characters (current VARCHAR(%d) maximum)", field.name, n, field.maxRunes)
}
}
return nil
}
type currentInt struct {
name string
value sql.NullInt64
}
func checkCurrentInts(fields ...currentInt) error {
for _, field := range fields {
if field.value.Valid && (field.value.Int64 < math.MinInt32 || field.value.Int64 > math.MaxInt32) {
return fmt.Errorf("legacy SQLite %s is %d (current INT range %d..%d)", field.name, field.value.Int64, math.MinInt32, math.MaxInt32)
}
}
return nil
}View on GitHub (pinned to 71377f2769)
Solutions
- Identify the field named in the error and shorten its value in the legacy SQLite database (e.g. UPDATE issues SET title = ... WHERE id = ...) before re-running the migration.
- Check the bd version that wrote the legacy DB; upgrade through an intermediate release that migrates oversized fields, if one exists.
- If the field is a label or external_ref, trim or split it to fit types.MaxFieldLen runes.
- For bulk fixes, script a pre-pass over the SQLite DB that flags every column whose utf8 rune length exceeds the reported maximum.
- If you believe the limit is wrong rather than the data, open an issue against beads rather than patching the reader locally.
Example fix
// before: legacy row with a 300-rune title // after: shorten before migration UPDATE issues SET title = substr(title, 1, 200) WHERE length(title) > 200;
Defensive patterns
Strategy: validation
Validate before calling
import "unicode/utf8"
func fieldFitsCurrentVarchar(name, value string, maxRunes int) error {
if n := utf8.RuneCountInString(value); n > maxRunes {
return fmt.Errorf("%s is %d characters (max %d)", name, n, maxRunes)
}
return nil
}
// run over title, labels, ids, external_ref before migration Type guard
func withinVarcharLimit(s string, maxRunes int) bool {
return utf8.RuneCountInString(s) <= maxRunes
} Prevention
- Pre-scan the legacy SQLite DB and truncate/trim fields exceeding current VARCHAR rune limits before migrating.
- Measure lengths in runes, not bytes, when auditing legacy text columns.
- Keep field lengths enforced at write time in the producing application so legacy data is born within limits.
- Log oversized fields during a dry-run pass so fixes can be batched.
When it happens
Trigger: Importing a legacy SQLite beads database whose issue title, id, assignee, external_ref, label, dependency type/created_by, or similar VARCHAR column holds more runes than the current limit (e.g. types.MaxFieldLen for ids/labels, currentTitleVarcharRunes for titles, currentShortVarcharRunes for status/type). Raised from checkCurrentVarchars via validateIssueVarchars, loadLabels, appendLegacyDependencyRow, and loadComments.
Common situations: Older bd versions stored longer titles or free-form external_refs before the current schema tightened VARCHAR widths; hand-edited databases with oversized labels; issues imported from other trackers with long IDs or actor names; multi-byte text where byte-count checks passed historically but rune counts now exceed the limit.
Related errors
- legacy SQLite foreign-key drift in %s
- legacy SQLite %s is %d (current INT range %d..%d)
- sealed legacy SQLite database does not match source fingerpr
- sealed legacy SQLite WAL does not match source fingerprint
- legacy SQLite source changed while sealing
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/079fe82bd49083a5.
Report an issue: GitHub.