{"record":{"id":"f029a31e241246b8","repo":"gastownhall/beads","slug":"failed-to-check-for-id-collision-w","errorCode":null,"errorMessage":"failed to check for ID collision: %w","messagePattern":"failed to check for ID collision: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/dolt/wisps.go","lineNumber":76,"sourceCode":"\t\t}\n\t}\n\n\tbaseLength := getAdaptiveIDLengthFromTable(ctx, tx, table, prefix)\n\n\tvar err error\n\tmaxLength := 8\n\tif baseLength > maxLength {\n\t\tbaseLength = maxLength\n\t}\n\n\tfor length := baseLength; length <= maxLength; length++ {\n\t\tfor nonce := 0; nonce < 10; nonce++ {\n\t\t\tcandidate := generateHashID(prefix, issue.Title, issue.Description, actor, issue.CreatedAt, length, nonce)\n\n\t\t\tvar count int\n\t\t\terr = tx.QueryRowContext(ctx, fmt.Sprintf(`SELECT COUNT(*) FROM %s WHERE id = ?`, table), candidate).Scan(&count) //nolint:gosec // G201\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to check for ID collision: %w\", err)\n\t\t\t}\n\n\t\t\tif count == 0 {\n\t\t\t\treturn candidate, nil\n\t\t\t}\n\t\t}\n\t}\n\n\treturn \"\", fmt.Errorf(\"failed to generate unique ID after trying lengths %d-%d with 10 nonces each\", baseLength, maxLength)\n}\n\n// getAdaptiveIDLengthFromTable returns the adaptive ID length based on table size.\n//\n//nolint:gosec // G201: table is a hardcoded constant\nfunc getAdaptiveIDLengthFromTable(ctx context.Context, tx *sql.Tx, table, prefix string) int {\n\tvar count int\n\tif err := tx.QueryRowContext(ctx, fmt.Sprintf(`SELECT COUNT(*) FROM %s WHERE id LIKE ?`, table), prefix+\"%\").Scan(&count); err != nil {\n\t\treturn 4 // Default for wisps (small tables)","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/dolt/wisps.go#L58-L94","documentation":"generateIssueIDInTable probes candidate hash IDs for collisions with SELECT COUNT(*) queries; if one of those collision-check queries fails, this error wraps the cause. It means the ID-generation loop could not even determine whether a candidate ID is free, so ID creation aborts. It is a database-level failure, not an actual ID collision.","triggerScenarios":"tx.QueryRowContext(...SELECT COUNT(*) FROM <table> WHERE id = ?...) returns an error: the transaction was aborted/rolled back by a prior error, the table does not exist, connection dropped mid-transaction, or a context deadline fires during the loop.","commonSituations":"Long ID-generation loops exceeding a context timeout under load; dropped DB connections; schema drift where the wisps/issues table is missing; transaction killed by a concurrent Dolt conflict.","solutions":["Inspect the wrapped error (%w) for the driver's root cause","Retry the operation; transient connection/context failures usually clear on retry","Verify the target table exists and the transaction is still alive before ID generation","Increase the context timeout if generation runs under heavy load with many collisions"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// preflight: confirm table reachable and tx viable\nctx, cancel := context.WithTimeout(ctx, 30*time.Second)\ndefer cancel()\nvar one int\nif err := db.QueryRowContext(ctx, `SELECT 1`).Scan(&one); err != nil {\n    return fmt.Errorf(\"database unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"id, err := store.CreateIssue(ctx, issue)\nif err != nil && strings.Contains(err.Error(), \"failed to check for ID collision\") {\n    // transient DB failure during generation — retry with backoff\n    time.Sleep(500 * time.Millisecond)\n    id, err = store.CreateIssue(ctx, issue)\n}","preventionTips":["Pass contexts with generous timeouts into create paths","Retry create operations on transient wrapped driver errors","Ensure schema migrations have created all issue/wisp tables before writes","Avoid sharing one aborted transaction across many generation probes"],"tags":["database","id-generation","transaction","go"],"backgroundTag":"db-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}