nats-io/nats-server · error · JSInvalidJSONError

JS_INVALID_JSON

JS_INVALID_JSON

Error message

consumer group not specified

What it means

A JSON validation error reported via NewJSInvalidJSONError (code JS_INVALID_JSON) in the distributed consumer-group (durable group) request handler: the request decoded fine but req.Group is empty, and a consumer group name is mandatory for this API. It is intentionally surfaced as an invalid-JSON/invalid-request style error to the client.

Source

Thrown at server/jetstream_api.go:3863

			return
		}
	}

	if errorOnRequiredApiLevel(hdr) {
		resp.Error = NewJSRequiredApiLevelError()
		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
		return
	}

	var req JSApiConsumerUnpinRequest
	if err := json.Unmarshal(msg, &req); err != nil {
		resp.Error = NewJSInvalidJSONError(err)
		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
		return
	}

	if req.Group == _EMPTY_ {
		resp.Error = NewJSInvalidJSONError(errors.New("consumer group not specified"))
		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
		return
	}

	if !validGroupName.MatchString(req.Group) {
		resp.Error = NewJSConsumerInvalidGroupNameError()
		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
		return
	}

	if hasJS, doErr := acc.checkJetStream(); !hasJS {
		if doErr {
			resp.Error = NewJSNotEnabledForAccountError()
			s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
		}
		return
	}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Add a non-empty "group" field to the request JSON.
  2. Fix JSON field tags/serialization so the group name actually populates req.Group.
  3. Validate the group name client-side (non-empty, matches validGroupName) before sending.
  4. Check templating/env substitution that may inject an empty group value.

Example fix

// before
{"stream": "ORDERS", "deliver_subject": "out.orders"} // missing group
// after
{"stream": "ORDERS", "group": "workers", "deliver_subject": "out.orders"}
Defensive patterns

Strategy: validation

Validate before calling

type groupReq struct {
    Stream string `json:"stream"`
    Group  string `json:"group"`
}
func validateGroupReq(b []byte) error {
    var r groupReq
    if err := json.Unmarshal(b, &r); err != nil { return err }
    if r.Group == "" { return errors.New("consumer group not specified") }
    if !regexp.MustCompile(`^[^ *>$]+$`).MatchString(r.Group) { return errors.New("invalid group name") }
    return nil
}

Try / catch

resp, err := nc.Request(subj, body, timeout)
if err != nil { return err }
var apiResp JSApiResponse
json.Unmarshal(resp.Data, &apiResp)
if apiResp.Error != nil && apiResp.Error.Code == 400 /* JS_INVALID_JSON */ {
    return fmt.Errorf("bad request: %s", apiResp.Error.Description)
}

Prevention

When it happens

Trigger: Posting a request to the consumer group API ($JS.API.CONSUMER.GROUP style endpoint, handler near jetstream_api.go:3863) with a JSON body lacking the "group" field or containing an empty string; the check `req.Group == _EMPTY_` fires before group-name validation.

Common situations: Omitting the group field in hand-written JSON; struct field tags mismatched so Group never deserializes; empty config values from template/CI variable substitution producing "".

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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