# panic: send on closed channel

- **ID:** `go/panic-runtime-error-send-on-closed-channel`
- **Domain:** go
- **Category:** runtime_error
- **Verification:** ai_generated
- **Fix Rate:** 85%

## Root Cause

Attempting to send a value on a channel that has already been closed, which violates the channel contract.

## Version Compatibility

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

## Workarounds

1. **Ensure the channel is closed only by the sender after all sends are complete. Use a sync.WaitGroup to coordinate goroutines, and close the channel in a dedicated goroutine after Wait.** (90% success)
   ```
   Ensure the channel is closed only by the sender after all sends are complete. Use a sync.WaitGroup to coordinate goroutines, and close the channel in a dedicated goroutine after Wait.
   ```
2. **Use a select statement with a default case to check if the channel is closed before sending, or use a separate closed channel for signaling.** (85% success)
   ```
   Use a select statement with a default case to check if the channel is closed before sending, or use a separate closed channel for signaling.
   ```

## Dead Ends

- **Adding a time.Sleep before closing the channel to avoid race conditions.** — Race conditions are timing-dependent; adding sleep does not guarantee ordering and may hide the bug rather than fix it. (85% fail)
- **Using recover() in a deferred function to catch the panic.** — Recovering from a panic does not fix the root cause; the channel was already misused and data may be lost. (70% fail)
- **Closing the channel after all sends are done by adding a sync.WaitGroup but not calling WaitGroup.Wait() correctly.** — Incorrect WaitGroup usage leads to same race: close happens before all sends complete. (60% fail)
