{"record":{"id":"cb7ad5e9ea0ad8a2","repo":"gastownhall/beads","slug":"legacy-sqlite-issue-s-has-invalid-created-at-or-u","errorCode":null,"errorMessage":"legacy SQLite issue %s has invalid created_at or updated_at","messagePattern":"legacy SQLite issue (.+?) has invalid created_at or updated_at","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/migration/legacysqlite/reader.go","lineNumber":559,"sourceCode":"\t\treturn fmt.Errorf(\"legacy SQLite issue %s created_at: %w\", issue.ID, err)\n\t}\n\tif issue.UpdatedAt, err = canonicalCurrentDatetime(issue.UpdatedAt); err != nil {\n\t\treturn fmt.Errorf(\"legacy SQLite issue %s updated_at: %w\", issue.ID, err)\n\t}\n\treturn nil\n}\n\n// checkRequiredScalars enforces the non-empty ID, non-tombstone status, and\n// present created_at/updated_at invariants every legacy issue must satisfy.\nfunc checkRequiredScalars(issue *types.Issue) error {\n\tif issue.ID == \"\" {\n\t\treturn fmt.Errorf(\"legacy SQLite issue has empty ID\")\n\t}\n\tif issue.Status == \"tombstone\" {\n\t\treturn fmt.Errorf(\"legacy SQLite issue %s is a tombstone\", issue.ID)\n\t}\n\tif issue.CreatedAt.IsZero() || issue.UpdatedAt.IsZero() {\n\t\treturn fmt.Errorf(\"legacy SQLite issue %s has invalid created_at or updated_at\", issue.ID)\n\t}\n\treturn nil\n}\n\n// checkRemovedFields rejects legacy rows that populate columns the current\n// schema no longer supports, then validates the tri-state boolean columns.\nfunc (x legacyExtras) checkRemovedFields(issue *types.Issue) error {\n\tif nonempty(x.closedBy, x.deletedBy, x.deleteReason, x.originalType, x.hookBead, x.roleBead, x.agentState, x.lastActivity, x.roleType, x.rig) || x.deletedAt.Valid || x.crystallizes.Int64 != 0 || x.quality.Valid || (issue.SourceRepo != \"\" && issue.SourceRepo != \".\") {\n\t\treturn fmt.Errorf(\"legacy SQLite issue %s uses unsupported removed fields\", issue.ID)\n\t}\n\tfor _, b := range []struct {\n\t\tname string\n\t\tv    sql.NullInt64\n\t}{{\"ephemeral\", x.ephemeral}, {\"pinned\", x.pinned}, {\"is_template\", x.template}} {\n\t\tif b.v.Valid && b.v.Int64 != 0 && b.v.Int64 != 1 {\n\t\t\treturn fmt.Errorf(\"issue %s has invalid %s boolean\", issue.ID, b.name)\n\t\t}\n\t}","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/migration/legacysqlite/reader.go#L541-L577","documentation":"checkRequiredScalars requires both created_at and updated_at to be present (non-zero) on every legacy issue. This error means the row carried a zero/missing timestamp even though it parsed successfully — the value was absent or epoch-zero rather than malformed.","triggerScenarios":"Legacy row has created_at or updated_at stored as NULL, empty, or a value that parses to time.Time zero (e.g. '0000-00-00' style placeholders).","commonSituations":"Rows inserted by scripts that omitted timestamps; imports from trackers that did not track update times; pre-dated rows from very early schema versions.","solutions":["Inspect the row: sqlite3 legacy.db \"SELECT id, created_at, updated_at FROM issues WHERE id='<id>'\"","Backfill the missing timestamp with a sensible value (file mtime, max of other rows' timestamps, or created_at as updated_at)","Add a NOT NULL / non-zero check to any tooling that writes to the legacy DB","Re-run the migration"],"exampleFix":"// before\ncreated_at = NULL, updated_at = NULL\n// after\nUPDATE issues SET created_at='2024-01-01T00:00:00Z', updated_at='2024-01-01T00:00:00Z' WHERE id='<id>';","handlingStrategy":"validation","validationCode":"-- run before migration\nSELECT id FROM issues\nWHERE created_at IS NULL OR created_at = ''\n   OR updated_at IS NULL OR updated_at = '';","typeGuard":"def has_timestamps(row) -> bool:\n    return bool(row.get('created_at')) and bool(row.get('updated_at'))","tryCatchPattern":null,"preventionTips":["Reject NULL/empty timestamps at write time in custom tooling","Backfill before migration rather than after","Prefer created_at as a safe fallback for missing updated_at"],"tags":["migration","sqlite","timestamps","data-integrity"],"backgroundTag":"missing-required-field","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}