{"record":{"id":"8a1f18bd721c036a","repo":"gastownhall/beads","slug":"failed-to-seed-issue-counter-for-prefix-q-w","errorCode":null,"errorMessage":"failed to seed issue counter for prefix %q: %w","messagePattern":"failed to seed issue counter for prefix %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/issues.go","lineNumber":873,"sourceCode":"\t// concurrent transactions (GH#2002). \"last_id = last_id + 1\" is evaluated\n\t// by the DB engine atomically within Dolt's MVCC.\n\n\t// Attempt atomic increment of an existing counter row.\n\tres, err := tx.ExecContext(ctx, \"UPDATE issue_counter SET last_id = last_id + 1 WHERE prefix = ?\", prefix)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to increment issue counter for prefix %q: %w\", prefix, err)\n\t}\n\n\trowsAffected, err := res.RowsAffected()\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to check rows affected for issue counter prefix %q: %w\", prefix, err)\n\t}\n\n\tif rowsAffected == 0 {\n\t\t// No counter row yet - seed from existing issues before proceeding to\n\t\t// avoid collisions with manually-created sequential IDs (GH#2002).\n\t\tif seedErr := seedCounterFromExistingIssuesTx(ctx, tx, prefix); seedErr != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to seed issue counter for prefix %q: %w\", prefix, seedErr)\n\t\t}\n\t\t// Retry the atomic increment after seeding.\n\t\tres, err = tx.ExecContext(ctx, \"UPDATE issue_counter SET last_id = last_id + 1 WHERE prefix = ?\", prefix)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to increment issue counter after seeding for prefix %q: %w\", prefix, err)\n\t\t}\n\t\trowsAffected, err = res.RowsAffected()\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to check rows affected after seeding for prefix %q: %w\", prefix, err)\n\t\t}\n\t\tif rowsAffected == 0 {\n\t\t\t// Seeding found no existing numeric IDs -- insert the initial row.\n\t\t\t_, err = tx.ExecContext(ctx, \"INSERT INTO issue_counter (prefix, last_id) VALUES (?, 1)\", prefix)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to insert initial issue counter for prefix %q: %w\", prefix, err)\n\t\t\t}\n\t\t}\n\t}","sourceCodeStart":855,"sourceCodeEnd":891,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/issues.go#L855-L891","documentation":"When no issue_counter row exists for the prefix, the code seeds one from existing issue IDs via seedCounterFromExistingIssuesTx to avoid colliding with manually-created sequential IDs (GH#2002). This error wraps any failure of that seeding step — typically an error scanning existing issue numbers or an insert/update failure while writing the seeded counter.","triggerScenarios":"First counter-mode ID generation in a database that never had a counter row for the prefix, where the seeding query over existing issues fails: issues table missing/unreadable, scan type mismatch on stored issue numbers, or the transaction aborted during seeding.","commonSituations":"Migrating an old hash-mode or JSON-exported database to counter mode; a database where issue IDs were created by another tool; partially restored .beads data where the issues table is inconsistent.","solutions":["Inspect the wrapped seed error; fix the underlying issues-table problem it reports (schema, corrupt rows, type mismatch).","Manually create the counter row seeded to the max existing numeric ID: INSERT INTO issue_counter (prefix, last_id) VALUES ('<prefix>', <max_id>) — then retry.","Verify the issues table contains parseable numeric suffixes for the prefix; clean malformed IDs.","Run bd doctor to check database consistency before retrying."],"exampleFix":"// before\nif seedErr := seedCounterFromExistingIssuesTx(ctx, tx, prefix); seedErr != nil {\n    return \"\", fmt.Errorf(\"failed to seed issue counter for prefix %q: %w\", prefix, seedErr)\n}\n// after (pre-seed the counter row outside of generation)\n// bd> INSERT INTO issue_counter (prefix, last_id) VALUES ('GH', 42);\n// then nextCounterIDTx skips the seeding path entirely\nres, err := tx.ExecContext(ctx, \"UPDATE issue_counter SET last_id = last_id + 1 WHERE prefix = ?\", prefix)","handlingStrategy":"validation","validationCode":"var lastID sql.NullInt64\nerr := db.QueryRow(\"SELECT MAX(CAST(SUBSTRING_INDEX(id,'-',-1) AS UNSIGNED)) FROM issues WHERE id LIKE ?\", prefix+\"-%\").Scan(&lastID)\nif err != nil {\n    return fmt.Errorf(\"issues table not seedable: %w\", err)\n}\n// pre-create the counter row so the seeding path never runs\n_, err = db.Exec(\"INSERT IGNORE INTO issue_counter (prefix, last_id) VALUES (?, ?)\", prefix, lastID.Int64)","typeGuard":null,"tryCatchPattern":"id, err := store.CreateIssue(ctx, issue)\nif err != nil && strings.Contains(err.Error(), \"failed to seed issue counter\") {\n    return fmt.Errorf(\"counter seeding failed; inspect issues table and pre-seed issue_counter: %w\", err)\n}","preventionTips":["Pre-seed issue_counter when migrating from hash-mode or imported databases","Keep issue IDs well-formed (prefix-N) so seeding can parse them","Run bd doctor on restored/converted databases before enabling counter mode","Enable counter mode once, with a single process, then share the repository"],"tags":["database","counter","seeding","migration"],"backgroundTag":"counter-seed-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}