{"record":{"id":"636c3425d4f99654","repo":"gastownhall/beads","slug":"db-eventssqlrepository-deleteallforids-rows-affec","errorCode":null,"errorMessage":"db: EventsSQLRepository.DeleteAllForIDs rows affected: %w","messagePattern":"db: EventsSQLRepository\\.DeleteAllForIDs rows affected: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/domain/db/events.go","lineNumber":67,"sourceCode":"\t\tplaceholders := make([]string, len(batch))\n\t\targs := make([]any, len(batch))\n\t\tfor i, id := range batch {\n\t\t\tplaceholders[i] = \"?\"\n\t\t\targs[i] = id\n\t\t}\n\t\t//nolint:gosec // G201: table is one of two hardcoded constants; ? placeholders only.\n\t\tres, err := r.runner.ExecContext(ctx,\n\t\t\tfmt.Sprintf(\"DELETE FROM %s WHERE issue_id IN (%s)\", table, strings.Join(placeholders, \",\")),\n\t\t\targs...)\n\t\tif err != nil {\n\t\t\tif opts.UseWispsTable && dberrors.IsTableNotExist(err) {\n\t\t\t\treturn total, nil\n\t\t\t}\n\t\t\treturn total, fmt.Errorf(\"db: EventsSQLRepository.DeleteAllForIDs from %s: %w\", table, err)\n\t\t}\n\t\tn, err := res.RowsAffected()\n\t\tif err != nil {\n\t\t\treturn total, fmt.Errorf(\"db: EventsSQLRepository.DeleteAllForIDs rows affected: %w\", err)\n\t\t}\n\t\ttotal += int(n)\n\t}\n\treturn total, nil\n}\n\nfunc (r *eventsSQLRepositoryImpl) CountAllForIDs(ctx context.Context, ids []string, opts domain.RecordEventOpts) (int, error) {\n\tif len(ids) == 0 {\n\t\treturn 0, nil\n\t}\n\ttable := \"events\"\n\tif opts.UseWispsTable {\n\t\ttable = \"wisp_events\"\n\t}\n\tcount, err := issueops.CountRowsForIssueIDsInTx(ctx, r.runner, table, ids)\n\tif err != nil {\n\t\tif opts.UseWispsTable && dberrors.IsTableNotExist(err) {\n\t\t\treturn 0, nil","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/events.go#L49-L85","documentation":"Wraps failures from res.RowsAffected() after a successful DELETE in DeleteAllForIDs. Some drivers can fail to report affected-row counts (e.g. unsupported or lost connection before metadata returns). The delete itself succeeded; only the count retrieval failed.","triggerScenarios":"Calling DeleteAllForIDs against a driver/server that doesn't populate RowsAffected for the executed statement, or whose connection dropped between DELETE completion and row-count retrieval.","commonSituations":"Proxy or pooler (e.g. some MySQL proxies) stripping OK-packet metadata; driver quirks with multi-statement or prepared DELETEs; connection reset right after execute.","solutions":["Check the wrapped error; if the connection was lost, reconnect and rerun (delete is idempotent for already-deleted rows)","If the driver never supports RowsAffected here, track counts via a SELECT COUNT before delete or accept approximate totals","Test against the exact Dolt/driver version in use; upgrade if a known RowsAffected bug exists"],"exampleFix":"// before\nn, err := res.RowsAffected()\nif err != nil { return total, err }\n// after\nn, rerr := res.RowsAffected()\nif rerr != nil {\n    log.Warnf(\"rows affected unavailable: %v\", rerr)\n    n = 0 // treat as unknown, continue\n}","handlingStrategy":"fallback","validationCode":"// no pre-call validation possible; failure occurs after successful delete","typeGuard":"func isRowsAffectedUnsupported(err error) bool {\n    return err != nil && (errors.Is(err, go_mysql.ErrSkip) || strings.Contains(err.Error(), \"RowsAffected\"))\n}","tryCatchPattern":"deleted, err := repo.DeleteAllForIDs(ctx, ids, opts)\nif err != nil {\n    if isRowsAffectedUnsupported(err) {\n        log.Warnf(\"row count unavailable; treat as unknown: %v\", err)\n        return nil // delete itself succeeded\n    }\n    return err\n}","preventionTips":["Test driver/proxy RowsAffected behavior in CI","Avoid proxies that strip OK-packet metadata","Prefer explicit COUNT queries when exact counts matter"],"tags":["database","driver","rows-affected","events"],"backgroundTag":"rows-affected-unavailable","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}