# sql: Rows are closed

- **ID:** `go/database-sql-rows-close-error`
- **Domain:** go
- **Category:** resource_error
- **Verification:** ai_generated
- **Fix Rate:** 78%

## Root Cause

Calling Scan or Next on a *sql.Rows object after it has been explicitly closed or after all rows have been exhausted without proper iteration.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| go1.21 | active | — | — |
| go1.22 | active | — | — |

## Workarounds

1. **Ensure rows.Next() loop runs to completion before accessing rows: for rows.Next() { ... }; if err := rows.Err(); err != nil { ... }** (92% success)
   ```
   Ensure rows.Next() loop runs to completion before accessing rows: for rows.Next() { ... }; if err := rows.Err(); err != nil { ... }
   ```
2. **Avoid calling rows.Close() before finishing iteration; let defer handle it after the loop.** (85% success)
   ```
   Avoid calling rows.Close() before finishing iteration; let defer handle it after the loop.
   ```

## Dead Ends

- **Adding defer rows.Close() after checking error but before iterating** — Deferring close doesn't prevent premature closure; the error occurs after rows are exhausted, not from missing close. (70% fail)
- **Calling rows.Close() multiple times** — Closing an already closed rows object is safe in Go, but doesn't fix the premature access; the root cause is logic error. (45% fail)
