gohugoio/hugo · error
received response for unknown call ID %d: WASM module violat
Error message
received response for unknown call ID %d: WASM module violated the RPC protocol
What it means
Raised in the dispatcher's response-reader goroutine (internal/warpc/warpc.go:439) when a JSON response from a WASM module carries a call ID that has no pending call in the dispatcher's map. Since IDs are assigned by Hugo and echoed by the module, an unknown ID means the module broke the request/response protocol (duplicate reply, reply after timeout cleanup, or corrupted stdout stream).
Source
Thrown at internal/warpc/warpc.go:439
defer d.mu.Unlock()
for _, call := range d.pending {
call.err = inputErr
call.done()
}
return inputErr
}
func (d *dispatcher[Q, R]) pendingCall(id uint32) *call[Q, R] {
d.mu.Lock()
defer d.mu.Unlock()
c, ok := d.pending[id]
if !ok {
// The WASM module wrote a response for an ID we never sent. This means it
// broke the RPC protocol, e.g. a corrupted stream after an error path that
// failed to drain its input or write a response. This is a bug in the
// module and should be reported.
panic(fmt.Errorf("received response for unknown call ID %d: WASM module violated the RPC protocol", id))
}
return c
}
type call[Q, R any] struct {
request Message[Q]
response Message[R]
responseKinds *maphelpers.ConcurrentMap[string, bool]
err error
donec chan *call[Q, R]
}
func (c *call[Q, R]) handleBlob(r io.Reader) error {
dest := any(c.request.Data).(DestinationProvider).GetDestination()
if dest == nil {
panic("blob destination is not set")
}
_, err := io.Copy(dest, r)View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Check the log for a preceding timeout on the same build — the late response is the follow-on symptom; address the timeout's cause.
- Re-run the build; transient module hiccups don't usually recur.
- Upgrade to the latest Hugo release in case of a fixed module bug.
- If reproducible, file a Hugo issue including the input that triggers it — this is an internal protocol violation, not a user config error.
Defensive patterns
Strategy: try-catch
Try / catch
if err != nil && strings.Contains(err.Error(), "unknown call ID") {
// protocol violation — restart the dispatcher/pool, report as a bug, never ignore
} Prevention
- This indicates a WASM module/runtime bug, not bad user input — report it upstream with the module version
- Restart the dispatcher rather than continuing on a desynced protocol stream
- Pin matching versions of the host and the embedded WASM modules
When it happens
Trigger: A WASM worker writes an extra or stray response on stdout — e.g. replying twice to one request, replying to a call already removed after a timeout, or emitting non-protocol output that parses as a message with a bogus ID.
Common situations: Usually follows a prior "timeout" error (the late reply arrives after the call was abandoned); a crashed/misbehaving module after a Hugo upgrade; custom or corrupted quickjs/katex WASM binaries; interleaved stdout corruption under heavy load.
Related errors
- received invalid image dimensions: %dx%d stride %d
- decoded AVIF buffer size %d is not a multiple of frame size
- ErrShutdown
- timeout
- webp codec is not available
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/7ecb8721aee14630.json.
Report an issue: GitHub ↗.