{"record":{"id":"1643755115f0df64","repo":"gastownhall/beads","slug":"failed-to-check-issue-counter-for-prefix-q-w","errorCode":null,"errorMessage":"failed to check issue_counter for prefix %q: %w","messagePattern":"failed to check issue_counter for prefix %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/issues.go","lineNumber":801,"sourceCode":"\treturn wrapExecError(\"record event\", issueops.RecordFullEventInTable(ctx, tx, \"events\", issueID, eventType, actor, oldValue, newValue))\n}\n\n// seedCounterFromExistingIssuesTx scans existing issues to find the highest numeric suffix\n// for the given prefix, then seeds the issue_counter table if no row exists yet.\n// This is called when counter mode is first enabled on a repo that already has issues,\n// to prevent counter collisions with manually-created sequential IDs (GH#2002).\n// It is idempotent: if a counter row already exists for this prefix, it does nothing.\nfunc seedCounterFromExistingIssuesTx(ctx context.Context, tx *sql.Tx, prefix string) error {\n\t// Check whether a counter row already exists for this prefix.\n\t// If it does, we must not overwrite it (the counter may already be in use).\n\tvar existing int\n\terr := tx.QueryRowContext(ctx, \"SELECT last_id FROM issue_counter WHERE prefix = ?\", prefix).Scan(&existing)\n\tif err == nil {\n\t\t// Row exists - counter is already initialized, nothing to do.\n\t\treturn nil\n\t}\n\tif err != sql.ErrNoRows {\n\t\treturn fmt.Errorf(\"failed to check issue_counter for prefix %q: %w\", prefix, err)\n\t}\n\n\t// No counter row yet. Scan existing issues to find the highest numeric suffix.\n\tlikePattern := prefix + \"-%\"\n\trows, err := tx.QueryContext(ctx, \"SELECT id FROM issues WHERE id LIKE ?\", likePattern)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to query existing issues for prefix %q: %w\", prefix, err)\n\t}\n\tdefer rows.Close()\n\n\tmaxNum := 0\n\tprefixDash := prefix + \"-\"\n\tfor rows.Next() {\n\t\tvar id string\n\t\tif err := rows.Scan(&id); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to scan issue id: %w\", err)\n\t\t}\n\t\t// Strip the prefix and attempt to parse the remainder as an integer.","sourceCodeStart":783,"sourceCodeEnd":819,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/issues.go#L783-L819","documentation":"seedCounterFromExistingIssuesTx initializes the issue_counter table by reading last_id for a prefix; if the SELECT fails with an error other than sql.ErrNoRows, it is wrapped here. This is a query failure, not a missing row (missing row is expected and handled by seeding).","triggerScenarios":"Generating the next counter-based ID (nextCounterIDTx) when the issue_counter SELECT fails — connection errors, table missing/corrupt, transaction aborted.","commonSituations":"Fresh or migrated databases where issue_counter schema is missing; transient Dolt server failures mid-transaction; corrupted database files.","solutions":["Read the wrapped cause; check server connectivity and retry","Verify the issue_counter table exists with columns (prefix, last_id); re-run schema migrations if not","Run bd doctor to check database integrity","If corruption is suspected, restore from backup or re-initialize the database"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Verify database schema before ID generation\nconst ok = await tableExists(\"issue_counter\"); // prefix TEXT, last_id BIGINT\nif (!ok) throw new Error(\"run migrations: issue_counter missing\");","typeGuard":null,"tryCatchPattern":"try {\n  await bd.create(title);\n} catch (e) {\n  if (String(e.message).includes(\"failed to check issue_counter\")) {\n    await runMigrations(); // then retry\n  } else throw e;\n}","preventionTips":["Keep schema migrations current so issue_counter always exists","Run bd doctor after database moves or restores","Retry transient connection errors with backoff","Monitor Dolt server health in automated pipelines"],"tags":["database","counter","query","storage"],"backgroundTag":"counter-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}