wavetermdev/waveterm · error
WriterChan: checksum mismatch
Error message
WriterChan: checksum mismatch
What it means
WriterChan streams packets received on a channel into an io.Writer while maintaining a running SHA-256 hash of the data. The sender transmits a final packet containing its checksum; when the receiver sees it, it compares that checksum against its locally computed hash. If they differ, the stream was corrupted, truncated, or reordered in transit, so the context is cancelled with this error.
Source
Thrown at pkg/util/iochan/iochan.go:91
case <-ctx.Done():
return
case resp, ok := <-ch:
if !ok {
return
}
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
- Compare against a fresh local copy of the source file/data to see where the streams diverged.
- Verify only one ReaderChan producer is feeding this WriterChan channel.
- Re-run the transfer; intermittent corruption may be a transient transport issue.
- Upgrade Wave Term on both ends to ensure matching ReaderChan/WriterChan checksum logic.
- Add logging of packet count and byte totals on both sides to pinpoint loss.
Example fix
// before: blind retry or ignoring the error
ch := iochan.ReaderChan(ctx, file, 65536, nil)
iochan.WriterChan(ctx, w, ch, nil, cancel)
// after: verify source integrity and retransfer once on mismatch
if isContextErrFrom(ctx, context.Cause(ctx), "checksum mismatch") {
log.Println("transfer corrupted, retransmitting")
seekAndRetransfer(ctx, w, file, 0)
} Defensive patterns
Strategy: validation
Validate before calling
func validateTransfer(src io.Reader, packetCh <-chan wshrpc.RespOrErrorUnion[iochantypes.Packet]) error {
h := sha256.New()
buf := make([]byte, 65536)
for {
n, err := src.Read(buf)
h.Write(buf[:n])
if err == io.EOF { break }
if err != nil { return err }
}
for p := range packetCh {
if p.Error != nil { return p.Error }
if p.Response.Checksum != nil {
if !bytes.Equal(h.Sum(nil), p.Response.Checksum) {
return errors.New("pre-transfer checksum mismatch")
}
return nil
}
}
return nil
} Type guard
func isChecksumMismatchErr(err error) bool {
return err != nil && strings.Contains(err.Error(), "WriterChan: checksum mismatch")
} Try / catch
if err := context.Cause(ctx); err != nil {
if isChecksumMismatchErr(err) {
log.Printf("transfer corrupted, discarding output and retrying: %v", err)
// re-run the transfer from a known-good source
} else {
return err
}
} Prevention
- Feed WriterChan from exactly one ReaderChan producer per channel.
- Verify transferred files against a known-good hash (sha256sum) after large transfers.
- Keep sender and receiver builds in sync so chunking/checksum logic matches.
- Never mutate packet Data in transit; pass channel packets through unchanged.
When it happens
Trigger: A packet's Data bytes were dropped, duplicated, or altered between ReaderChan (sender) and WriterChan (receiver) — e.g. an RPC layer dropped/duplicated channel packets, two different streams were interleaved into the same channel, or a sender bug wrote data outside of ReaderChan so the checksums were computed over different byte sequences.
Common situations: File transfer over wsh RPC failing mid-download with corrupted output; intermediate middleware that re-orders or drops packets from the channel; the writer receiving packets from more than one producer; version mismatch where sender and receiver chunk/hash differently.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- reading file: %w
- no pending stream (call PrepareConnect first)
- failed to set rwnd size: %w
- stream broker not available
- starting remote file stream: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/9940c37d9d34d1b2.
Report an issue: GitHub.