gastownhall/beads · error
legacy SQLite issue waiters serialize to %d bytes (current T
Error message
legacy SQLite issue waiters serialize to %d bytes (current TEXT maximum %d)
What it means
validateCurrentTextBytes also serializes the issue's Waiters list via issueops.FormatJSONStringArray and enforces the same TEXT byte limit. If the serialized waiters JSON exceeds currentTextBytes, the migration rejects the row.
Source
Thrown at internal/migration/legacysqlite/reader.go:683
return fmt.Errorf("lone high UTF-16 surrogate escape")
}
i = next + 5
case code >= 0xdc00 && code <= 0xdfff:
return fmt.Errorf("lone low UTF-16 surrogate escape")
default:
i += 5
}
}
return nil
}
func validateCurrentTextBytes(issue *types.Issue) error {
if len(issue.Payload) > currentTextBytes {
return fmt.Errorf("legacy SQLite issue payload is %d bytes (current TEXT maximum %d)", len(issue.Payload), currentTextBytes)
}
waiters := issueops.FormatJSONStringArray(issue.Waiters)
if len(waiters) > currentTextBytes {
return fmt.Errorf("legacy SQLite issue waiters serialize to %d bytes (current TEXT maximum %d)", len(waiters), currentTextBytes)
}
return nil
}
func decodeWaiters(raw string) ([]string, error) {
var decoded any
if err := json.Unmarshal([]byte(raw), &decoded); err != nil {
return nil, err
}
values, ok := decoded.([]any)
if !ok {
return nil, fmt.Errorf("must be an array of strings")
}
waiters := make([]string, len(values))
for i, value := range values {
waiter, ok := value.(string)
if !ok {
return nil, fmt.Errorf("element %d is not a string", i)View on GitHub (pinned to 71377f2769)
Solutions
- Reduce the waiter list on the legacy issue before migrating (drop stale waiters).
- Increase the target TEXT limit if the schema permits.
- Migrate with waiters truncated and re-add waiters post-migration.
Example fix
// before waiters := issue.Waiters // 10,000 entries migrated as-is // after issue.Waiters = issue.Waiters[:maxWaiters]
Defensive patterns
Strategy: validation
Validate before calling
if n := len(issueops.FormatJSONStringArray(issue.Waiters)); n > currentTextBytes { return fmt.Errorf("waiters too large: %d > %d", n, currentTextBytes) } Try / catch
if err := validateCurrentTextBytes(issue); err != nil { log.Warn("trimming waiters for", issue.ID); issue.Waiters = nil } Prevention
- Cap waiter list length at the application layer
- Prune stale waiters in the legacy system before migrating
- Serialize and size-check large rows during export dry-runs
When it happens
Trigger: len(FormatJSONStringArray(issue.Waiters)) > currentTextBytes during validate().
Common situations: Legacy issues with hundreds/thousands of waiting actors (long waiter lists), producing a JSON array larger than the column limit.
Related errors
- legacy SQLite issue payload is %d bytes (current TEXT maximu
- legacy SQLite ephemeral comment text is %d bytes (current TE
- 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/857bfd06c0e07602.
Report an issue: GitHub.