nats-io/nats-server · warning

%w at offset %d

Error message

%w at offset %d

What it means

When a JetStream API request body fails to parse as JSON, the server wraps the underlying error with the byte offset of the syntax error (from json.SyntaxError.Offset) and rate-limit-logs it. With strict JetStream mode enabled, the wrapped error is also returned to the client, pinpointing where the malformed JSON broke.

Source

Thrown at server/jetstream_api.go:1299

	if acc == nil {
		return nil, nil, nil, nil, ErrMissingAccount
	}
	return &ci, acc, hdr, msg, nil
}

func (s *Server) unmarshalRequest(c *client, acc *Account, subject string, msg []byte, v any) error {
	decoder := json.NewDecoder(bytes.NewReader(msg))
	decoder.DisallowUnknownFields()

	for {
		if err := decoder.Decode(v); err != nil {
			if err == io.EOF {
				return nil
			}

			var syntaxErr *json.SyntaxError
			if errors.As(err, &syntaxErr) {
				err = fmt.Errorf("%w at offset %d", err, syntaxErr.Offset)
			}

			c.RateLimitWarnf("Invalid JetStream request '%s > %s': %s", acc, subject, err)

			if js := s.getJetStream(); js != nil && js.config.Strict {
				return err
			}

			return json.Unmarshal(msg, v)
		}
	}
}

func (a *Account) trackAPI() {
	a.mu.RLock()
	jsa := a.js
	a.mu.RUnlock()
	if jsa != nil {

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Use the offset in the message to locate the first invalid byte in your request payload and fix the JSON there.
  2. Serialize the request with a proper JSON encoder (e.g. json.Marshal of the API request struct) instead of manual string building.
  3. Validate the payload parses (json.Valid) before publishing to $JS.API subjects.

Example fix

// before
nc.Publish("$JS.API.STREAM.CREATE.x", []byte(`{"name":"x"`)) // truncated
// after
cfg, _ := json.Marshal(&JetStreamStreamCreateRequest{Name: "x"})
nc.Publish("$JS.API.STREAM.CREATE.x", cfg)
Defensive patterns

Strategy: try-catch

Validate before calling

if !json.Valid(payload) {
    return errors.New("request payload is not valid JSON")
}

Try / catch

// Go: inspect wrapped json.SyntaxError for offset
var syn *json.SyntaxError
if errors.As(err, &syn) {
    log.Printf("bad JetStream request at offset %d", syn.Offset)
}

Prevention

When it happens

Trigger: Publishing to a $JS.API subject with a body that is not valid JSON — truncated message, wrong encoding, concatenation of two JSON docs, or a non-JSON payload sent to an API endpoint.

Common situations: Client sending protobuf/msgpack instead of JSON to JetStream API; string-concatenated payloads with trailing bytes; network truncation of large requests; handcrafted test payloads.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/007f08bc95ec0f72. Report an issue: GitHub.