gastownhall/beads · error
truncated JSON Unicode escape
Error message
truncated JSON Unicode escape
What it means
checkJSONSurrogates validates \uXXXX escapes in metadata strings. If a backslash is followed by 'u' but fewer than four hex digits remain in the string, the Unicode escape is incomplete and cannot be decoded, so the migration returns 'truncated JSON Unicode escape'.
Source
Thrown at internal/migration/legacysqlite/reader.go:651
}
}
return nil
}
func checkJSONSurrogates(raw string) error {
for i := 0; i < len(raw); i++ {
if raw[i] != '\\' {
continue
}
if i+1 >= len(raw) {
return fmt.Errorf("truncated JSON escape")
}
if raw[i+1] != 'u' {
i++
continue
}
if i+6 > len(raw) {
return fmt.Errorf("truncated JSON Unicode escape")
}
code, err := strconv.ParseUint(raw[i+2:i+6], 16, 16)
if err != nil {
return fmt.Errorf("invalid JSON Unicode escape")
}
switch {
case code >= 0xd800 && code <= 0xdbff:
next := i + 6
if next+6 > len(raw) || raw[next] != '\\' || raw[next+1] != 'u' {
return fmt.Errorf("lone high UTF-16 surrogate escape")
}
low, err := strconv.ParseUint(raw[next+2:next+6], 16, 16)
if err != nil || low < 0xdc00 || low > 0xdfff {
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")View on GitHub (pinned to 71377f2769)
Solutions
- Locate and repair the truncated \uXXXX escape in the legacy row (complete the four hex digits or remove the partial escape).
- Re-export the legacy database without byte truncation.
- Sanitize inputs to expand or strip partial Unicode escapes before migration.
Example fix
// before "label": "caf\u00 // after "label": "caf\u00e9"
Defensive patterns
Strategy: validation
Validate before calling
for i := 0; i+1 < len(raw); i++ { if raw[i]=='\\' && raw[i+1]=='u' && i+6 > len(raw) { return fmt.Errorf("truncated \\u escape at %d", i) } } Type guard
func completeUnicodeEscapes(s string) bool { for i := 0; i < len(s); i++ { if s[i]=='\\' && i+1 < len(s) && s[i+1]=='u' && i+6 > len(s) { return false } }; return true } Prevention
- Avoid byte-level truncation of text columns
- Re-encode legacy text to direct UTF-8 rather than \u escapes
- Run a JSON validity check on exported rows before migration
When it happens
Trigger: A raw string contains '\u' (or '\u1') within the last 5 bytes so that i+6 exceeds len(raw).
Common situations: Legacy rows truncated mid-escape by a byte-limit, corrupted exports, or manual edits that cut a string in the middle of a \uXXXX sequence.
Related errors
- invalid JSON Unicode escape
- legacy SQLite issue %s metadata: %w
- truncated JSON escape
- parsing legacy config: %w
- legacy SQLite issue %s has invalid metadata JSON
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/b5927356bac9dfec.
Report an issue: GitHub.