gastownhall/beads · error

legacy SQLite issue payload is %d bytes (current TEXT maximu

Error message

legacy SQLite issue payload is %d bytes (current TEXT maximum %d)

What it means

validateCurrentTextBytes enforces the current storage TEXT column limit (currentTextBytes) on migrated issues. If the issue's serialized Payload exceeds that limit, the migration refuses the row rather than risk a database write failure downstream.

Source

Thrown at internal/migration/legacysqlite/reader.go:679

				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")
		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))

View on GitHub (pinned to 71377f2769)

Solutions

  1. Trim or split the oversized issue payload before migrating.
  2. Increase the target TEXT column limit if the storage backend allows it.
  3. Archive the large legacy issue externally and migrate a truncated placeholder.

Example fix

// before: payload of 2,000,000 bytes migrated as-is
// after
payload := truncateToBytes(issue.Payload, currentTextBytes)
Defensive patterns

Strategy: validation

Validate before calling

if len(issue.Payload) > currentTextBytes { return fmt.Errorf("payload too large: %d > %d", len(issue.Payload), currentTextBytes) }

Try / catch

if err := validateCurrentTextBytes(issue); err != nil { log.Warn("skipping oversized issue", issue.ID); continue }

Prevention

When it happens

Trigger: len(issue.Payload) > currentTextBytes for an issue read from the legacy SQLite database during validate().

Common situations: Legacy rows containing very large issue bodies accumulated over years, attachments embedded as text, or a lowered TEXT limit in the current schema.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/308e62883011ed3c. Report an issue: GitHub.