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

  1. Check the log for a preceding timeout on the same build — the late response is the follow-on symptom; address the timeout's cause.
  2. Re-run the build; transient module hiccups don't usually recur.
  3. Upgrade to the latest Hugo release in case of a fixed module bug.
  4. 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

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


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/7ecb8721aee14630.json. Report an issue: GitHub ↗.