wavetermdev/waveterm · error
WriterChan: write error: %v
Error message
WriterChan: write error: %v
What it means
WriterChan receives data packets from a channel and writes them to the destination io.Writer. When the underlying Write call returns an error (disk full, closed pipe, broken connection, permission denied), the streaming context is cancelled with 'WriterChan: write error: <underlying error>'. The wrapped error message contains the real cause.
Source
Thrown at pkg/util/iochan/iochan.go:96
}
if resp.Error != nil {
cancel(resp.Error)
return
}
if _, err := sha256Hash.Write(resp.Response.Data); err != nil {
cancel(fmt.Errorf("WriterChan: error writing to sha256 hash: %v", err))
return
}
// The checksum is sent as the last packet
if resp.Response.Checksum != nil {
localChecksum := sha256Hash.Sum(nil)
if !bytes.Equal(localChecksum, resp.Response.Checksum) {
cancel(fmt.Errorf("WriterChan: checksum mismatch"))
}
return
}
if _, err := w.Write(resp.Response.Data); err != nil {
cancel(fmt.Errorf("WriterChan: write error: %v", err))
return
}
}
}
}()
}
View on GitHub (pinned to a4447c1563)
Solutions
- Inspect the wrapped error text after this message for the root cause (e.g. 'no space left on device', 'file already closed', 'broken pipe').
- Free disk space or fix permissions on the destination before retrying.
- Keep the destination io.Writer open until the context is done; close it only after WriterChan finishes (callback).
- If the destination is a network stream, reconnect and restart the transfer.
- Handle SIGPIPE/broken-pipe cases by cancelling the sender early rather than continuing to read.
Example fix
// before: closing the file while WriterChan may still write
f, _ := os.Create(dest)
iochan.WriterChan(ctx, f, ch, nil, cancel)
f.Close()
// after: close only after the writer goroutine completes
done := make(chan struct{})
iochan.WriterChan(ctx, f, ch, func() { close(done) }, cancel)
<-done
f.Close() Defensive patterns
Strategy: try-catch
Validate before calling
f, err := os.OpenFile(dest, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil { return err }
if stat, err := f.Stat(); err == nil {
if avail, _ := diskFree(destDir); avail < expectedSize { return errors.New("insufficient disk space") }
_ = stat
} Type guard
func isWriteError(err error) bool {
return err != nil && strings.Contains(err.Error(), "WriterChan: write error:")
} Try / catch
if err := context.Cause(ctx); err != nil {
if isWriteError(err) {
log.Printf("destination write failed: %v", err)
// inspect wrapped cause: ENOSPC, EPIPE, permission denied, etc.
return fmt.Errorf("cannot write destination: %w", err)
}
return err
} Prevention
- Keep the destination io.Writer open until WriterChan's callback fires; close it afterwards.
- Check disk space and write permissions on the destination before large transfers.
- Avoid sharing one io.Writer across concurrent WriterChan goroutines.
- Detect destination closure (pipe/ssh disconnect) and cancel the sender promptly.
When it happens
Trigger: Calling WriterChan with an io.Writer whose Write fails: writing to a closed file/socket, disk full, permission denied on the output file, writing to an io.Writer already closed by another goroutine, or a network writer whose peer disconnected.
Common situations: Downloading a remote file into a local file that was deleted or hit its quota; writing to an os.Pipe whose reader closed; output stream to a terminal/ssh session that was closed mid-transfer.
Related errors
- reading file stream: %w
- reading input: %w
- reading file: %w
- reading input: %w
- no pending stream (call PrepareConnect first)
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/4ca17d68b8035cbc.
Report an issue: GitHub.