hashicorp/nomad · error

failed to marshal json from Topic: %s, Type: %s, Err: %w

Error message

failed to marshal json from Topic: %s, Type: %s, Err: %w

What it means

For each non-error, non-heartbeat event, captureEventStream serializes the whole event struct with json.Marshal before writing it to eventstream.json. If marshaling fails, the event cannot be recorded and the failure is appended to the multierror with the event's Topic and Type. json.Marshal on well-formed event structs essentially only fails on unsupported channel/func/custom-marshaler values, so this usually indicates an unexpected event payload or a library-level serialization bug.

Source

Thrown at command/operator_debug.go:986

				errCount++
				c.verboseOutf("error from event stream: index; %d err: %v", event.Index, event.Err)
				mErrs = multierror.Append(mErrs, fmt.Errorf("error at index: %d, Err: %w", event.Index, event.Err))
				break
			}

			if event.IsHeartbeat() {
				heartbeatCount++
				continue
			}

			for _, e := range event.Events {
				eventCount++
				c.verboseOutf("Event: %4d, Index: %d, Topic: %-10s, Type: %s, FilterKeys: %s", eventCount, e.Index, e.Topic, e.Type, e.FilterKeys)

				bytes, err := json.Marshal(e)
				if err != nil {
					errCount++
					mErrs = multierror.Append(mErrs, fmt.Errorf("failed to marshal json from Topic: %s, Type: %s, Err: %w", e.Topic, e.Type, err))
				}

				n, err := fh.Write(bytes)
				if err != nil {
					errCount++
					mErrs = multierror.Append(mErrs, fmt.Errorf("failed to write bytes to eventstream.json; bytes written: %d, Err: %w", n, err))
					break
				}
				n, err = fh.WriteString("\n")
				if err != nil {
					errCount++
					mErrs = multierror.Append(mErrs, fmt.Errorf("failed to write string to eventstream.json; chars written: %d, Err: %w", n, err))
				}
			}
		case <-c.ctx.Done():
			c.verboseOutf("Event stream captured %d events, %d frames, %d heartbeats, %d errors", eventCount, channelEventCount, heartbeatCount, errCount)
			return mErrs.ErrorOrNil()
		}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Record the Topic and Type in the message and check whether that topic's events changed with a recent Consul version — upgrade/downgrade the CLI to match the agent
  2. Retry the capture; a single malformed frame loses only that event (errCount is tracked, loop continues)
  3. Update the consul CLI to a version whose event types marshal cleanly for your agent version
  4. If reproducible, report the unserializable Topic/Type upstream — this indicates a marshaling bug
Defensive patterns

Strategy: try-catch

Try / catch

bytes, err := json.Marshal(e)
if err != nil {
	errs = multierror.Append(errs, fmt.Errorf("failed to marshal json from Topic: %s, Type: %s, Err: %w", e.Topic, e.Type, err))
	continue // skip unserializable event, keep capture alive
}

Prevention

When it happens

Trigger: json.Marshal(e) returns an error for a received event — e.g. an event type carrying a value its custom MarshalJSON rejects, or an internal field that cannot be represented in JSON.

Common situations: Capturing topics whose event payloads include exotic data; version mismatch between the CLI and the agent producing newer event fields with unsupported types; a bug in a custom MarshalJSON implementation.

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


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/0cb09509b819d8c2. Report an issue: GitHub.