{"record":{"id":"1e4da82b176c1e9f","repo":"gastownhall/beads","slug":"db-rawsql-exec-rows-affected-w","errorCode":null,"errorMessage":"db: RawSQL Exec: rows affected: %w","messagePattern":"db: RawSQL Exec: rows affected: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/storage/domain/db/raw_sql.go","lineNumber":62,"sourceCode":"\t\t\t\tvalues[i] = string(b)\n\t\t\t}\n\t\t}\n\t\tresult.Rows = append(result.Rows, values)\n\t}\n\tif err := rows.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"db: RawSQL Query: rows: %w\", err)\n\t}\n\treturn result, nil\n}\n\nfunc (r *rawSQLRepositoryImpl) Exec(ctx context.Context, query string, args ...any) (int64, error) {\n\tres, err := r.runner.ExecContext(ctx, query, args...)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"db: RawSQL Exec: %w\", err)\n\t}\n\taffected, err := res.RowsAffected()\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"db: RawSQL Exec: rows affected: %w\", err)\n\t}\n\treturn affected, nil\n}\n","sourceCodeStart":44,"sourceCodeEnd":66,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/raw_sql.go#L44-L66","documentation":"Wraps a failure from sql.Result.RowsAffected after a successful Exec in RawSQLRepository.Exec. Some drivers cannot report affected-row counts for certain statements, and the driver can also fail here if the connection state is gone. The statement executed but the library cannot tell you how many rows it touched.","triggerScenarios":"Calling Exec with a statement whose driver (or underlying engine) does not produce a rows-affected count, or where the result handle is invalid because the connection dropped after execution.","commonSituations":"Statements like DDL (CREATE/ALTER) or some multi-statement/SET commands where affected counts are meaningless; drivers lacking LastInsertId/RowsAffected support; connection reset immediately after exec.","solutions":["Treat the count as optional — if you don't need it, prefer a driver/connection that supports RowsAffected or ignore 0","Avoid Exec for DDL when you rely on affected counts","Check driver support; upgrade if RowsAffected is unimplemented","Verify connection stability — a drop right after exec yields an unusable result handle"],"exampleFix":"// before: relying on the count for a DDL statement\nn, err := repo.Exec(ctx, \"ALTER TABLE issues ADD INDEX idx_p (priority)\")\n// after: don't depend on the affected count for DDL\n_, err = repo.Exec(ctx, \"ALTER TABLE issues ADD INDEX idx_p (priority)\")","handlingStrategy":"fallback","validationCode":"// don't rely on affected counts for DDL; classify the statement first\nisDDL := strings.HasPrefix(strings.ToUpper(strings.TrimSpace(stmt)), \"ALTER\") ||\n\tstrings.HasPrefix(strings.ToUpper(strings.TrimSpace(stmt)), \"CREATE\")","typeGuard":"func isRowsAffectedError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"RawSQL Exec: rows affected\")\n}","tryCatchPattern":"n, err := repo.Exec(ctx, stmt)\nif isRowsAffectedError(err) {\n\t// statement ran; proceed treating the count as unknown\n\treturn lastErr /* or continue without the count */\n}","preventionTips":["Ignore affected counts for DDL statements","Confirm the driver implements RowsAffected for your statements","Avoid multi-statement Exec calls when counts matter","Keep connections alive through exec + result read"],"tags":["database","sql","rows-affected","driver"],"backgroundTag":"rows-affected-unsupported","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}