{"record":{"id":"42db2d0d53ee37ad","repo":"gastownhall/beads","slug":"legacy-sqlite-issue-s-w","errorCode":null,"errorMessage":"legacy SQLite issue %s: %w","messagePattern":"legacy SQLite issue (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/migration/legacysqlite/reader.go","lineNumber":481,"sourceCode":"\t}\n\tif err := checkCurrentInts(\n\t\tcurrentInt{\"issue estimated_minutes\", x.estimatedMinutes},\n\t\tcurrentInt{\"issue compaction_level\", x.compactionLevel},\n\t\tcurrentInt{\"issue original_size\", x.originalSize},\n\t); err != nil {\n\t\treturn err\n\t}\n\tif err := x.applyCanonicalTimestamps(issue); err != nil {\n\t\treturn err\n\t}\n\tif err := checkRequiredScalars(issue); err != nil {\n\t\treturn err\n\t}\n\tif err := x.checkRemovedFields(issue); err != nil {\n\t\treturn err\n\t}\n\tif err := issue.Validate(); err != nil {\n\t\treturn fmt.Errorf(\"legacy SQLite issue %s: %w\", issue.ID, err)\n\t}\n\treturn nil\n}\n\n// applyOptionalTimestamps parses the legacy issue's optional timestamp columns\n// (closed_at, compacted_at, due_at, defer_until) and assigns them to issue.\nfunc (x legacyExtras) applyOptionalTimestamps(issue *types.Issue) error {\n\tvar err error\n\tif issue.ClosedAt, err = parseOptionalTime(\"closed_at\", x.closedAt); err != nil {\n\t\treturn fmt.Errorf(\"legacy SQLite issue %s: %w\", issue.ID, err)\n\t}\n\tif issue.CompactedAt, err = parseOptionalTime(\"compacted_at\", x.compactedAt); err != nil {\n\t\treturn fmt.Errorf(\"legacy SQLite issue %s: %w\", issue.ID, err)\n\t}\n\tif issue.DueAt, err = parseOptionalTime(\"due_at\", x.dueAt); err != nil {\n\t\treturn fmt.Errorf(\"legacy SQLite issue %s: %w\", issue.ID, err)\n\t}\n\tif issue.DeferUntil, err = parseOptionalTime(\"defer_until\", x.deferUntil); err != nil {","sourceCodeStart":463,"sourceCodeEnd":499,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/migration/legacysqlite/reader.go#L463-L499","documentation":"During loadIssues, each scanned legacy issue is validated by issue.Validate(); any validation failure is wrapped as 'legacy SQLite issue <id>: <reason>'. This means the legacy row's data violates issue invariants (e.g. missing/invalid status, bad priority, empty ID, invalid field values), so the issue cannot be safely imported.","triggerScenarios":"Migrating a legacy SQLite DB where an issues row has field values that fail types.Issue.Validate — for example an unknown status enum value, invalid priority, out-of-range or malformed fields.","commonSituations":"Legacy DBs written by old beads versions whose status/priority vocabularies changed; rows corrupted by manual SQL edits; data imported from another tracker with non-canonical enum values; half-finished writes in the legacy DB.","solutions":["Read the wrapped inner message to see which field failed validation, then fix that row's column values in the legacy DB (e.g. normalize status/priority to current enum values).","Identify the offending issue ID from the error and repair or delete the row, then re-run migration.","Check whether the legacy DB predates a schema/vocabulary change and run any needed upgrade steps before migrating.","Export the row, validate it offline, and re-import after correction."],"exampleFix":"-- before (row fails validation)\nUPDATE issues SET status='in_progress' WHERE id='bd-42';\n-- after (canonical enum value)\nUPDATE issues SET status='in_progress' WHERE id='bd-42' AND status IN ('open','in_progress','closed');","handlingStrategy":"validation","validationCode":"// before migration, check enum values\nrows, _ := db.Query(`SELECT id FROM issues WHERE status NOT IN ('open','in_progress','closed') OR priority NOT IN (0,1,2,3,4)`)\n// fix reported rows first","typeGuard":null,"tryCatchPattern":"if err := loadIssues(...); err != nil {\n  var issueID string\n  if _, scanErr := fmt.Sscanf(err.Error(), \"legacy SQLite issue %s\", &issueID); scanErr == nil {\n    // inspect and repair that row in the legacy DB\n  }\n  return err\n}","preventionTips":["Run a pre-migration audit query for invalid enum values in issues.","Keep legacy DBs on the beads version that wrote them until migration.","Never INSERT into legacy issues tables with raw SQL.","Validate a copy of the DB first; migrate only after verify passes."],"tags":["sqlite","migration","data-validation"],"backgroundTag":"legacy-issue-validation-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}