hashicorp/nomad · error
error marshaling json for stream: %w
Error message
error marshaling json for stream: %w
What it means
The NDJSON stream writer (used for exec streaming and event streams) encodes each outgoing value with a codec (JSON with extensions) before pushing to outCh. If enc.Encode fails — the value is not JSON-encodable (unsupported types, unserializable extensions, invalid map keys) — Send returns this wrapped error and the stream aborts.
Source
Thrown at nomad/stream/ndjson.go:85
case <-n.ctx.Done():
return
}
}
}
}
// Send encodes an object into Newline delimited json. An error is returned
// if json encoding fails or if the stream is no longer running.
func (n *JsonStream) Send(v any) error {
if n.ctx.Err() != nil {
return n.ctx.Err()
}
var buf bytes.Buffer
enc := codec.NewEncoder(&buf, structs.JsonHandleWithExtensions)
err := enc.Encode(v)
if err != nil {
return fmt.Errorf("error marshaling json for stream: %w", err)
}
select {
case <-n.ctx.Done():
return fmt.Errorf("error stream is no longer running: %w", err)
case n.outCh <- &structs.EventJson{Data: buf.Bytes()}:
}
return nil
}
View on GitHub (pinned to 482b49bf1a)
Solutions
- Log the wrapped cause and inspect the value being sent for non-encodable fields (func, chan, cycles, invalid map keys).
- Sanitize/normalize the payload before Send (convert binary data to base64 strings; only send documented structs like structs.StreamFrame / EventJson).
- Add a test asserting the exact payload type marshals with structs.JsonHandleWithExtensions.
- If caused by a Nomad version's exec protocol mismatch, upgrade client and server together.
Example fix
// before
err := stream.Send(rawMsg) // rawMsg contains []byte fields
// after
safe := struct {
Data string `json:"data"`
}{Data: base64.StdEncoding.EncodeToString(rawMsg.Data)}
if err := stream.Send(safe); err != nil { return err } Defensive patterns
Strategy: validation
Validate before calling
// Ensure the payload is JSON-encodable with the same codec before Send
func assertEncodable(v interface{}) error {
var buf bytes.Buffer
return codec.NewEncoder(&buf, structs.JsonHandleWithExtensions).Encode(v)
} Type guard
func isStreamMarshalError(err error) bool { return err != nil && strings.Contains(err.Error(), "error marshaling json for stream") } Try / catch
if err := n.Send(v); err != nil {
if isStreamMarshalError(err) {
logger.Error("unencodable stream payload", "type", fmt.Sprintf("%T", v), "err", err)
return err // stream aborted; do not retry same payload
}
return err
} Prevention
- Only send documented stream structs (StreamFrame, EventJson) over NDJSON streams.
- Encode binary data as base64; avoid func/chan/cyclic fields in payloads.
- Add unit tests that marshal payloads with structs.JsonHandleWithExtensions.
When it happens
Trigger: Calling n.Send(v) (jsonStream, exec streaming handlers like execStreaming/ExecTaskStreamingRaw) with a value that codec/Encode cannot marshal to JSON with extensions.
Common situations: Sending raw messages containing non-UTF-8 bytes or invalid types in an exec stdin/stdout frame; custom structs with channels/funcs or cyclic references accidentally passed to the stream; msgpack-style extension data that violates the JSON handle rules.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- failed to marshal json from Topic: %s, Type: %s, Err: %w
- missing AllocID
- <remote node streaming RPC error relayed from ack.Error>
- subscription closed by server, client should resubscribe
- failed to decode and failed to read buffered data: %w
AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04).
Data as JSON: /api/errors/5164a55ec821294e.
Report an issue: GitHub.