nats-io/nats-server · warning

subject %q is malformed

Error message

subject %q is malformed

What it means

This internal error is produced by the monitoring/system-account service setup in events.go when a request subject received on an internal system service does not tokenize into the expected number of tokens (accReqTokens, e.g. '$SYS.REQ.ACCOUNT.<account>.<endpoint>'). The library throws it to skip a malformed system request it cannot attribute to an account.

Source

Thrown at server/events.go:1364

		case "STATSZ":
			h = s.noInlineCallbackStatsz(req)
		default:
			h = s.noInlineCallback(req)
		}
		subject = fmt.Sprintf(serverDirectReqSubj, s.info.ID, name)
		if _, err := s.sysSubscribe(subject, h); err != nil {
			s.Errorf("Error setting up internal tracking: %v", err)
			return
		}
		subject = fmt.Sprintf(serverPingReqSubj, name)
		if _, err := s.sysSubscribe(subject, h); err != nil {
			s.Errorf("Error setting up internal tracking: %v", err)
			return
		}
	}
	extractAccount := func(subject string) (string, error) {
		if tk := strings.Split(subject, tsep); len(tk) != accReqTokens {
			return _EMPTY_, fmt.Errorf("subject %q is malformed", subject)
		} else {
			return tk[accReqAccIndex], nil
		}
	}
	monAccSrvc := map[string]sysMsgHandler{
		"SUBSZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) {
			optz := &SubszEventOptions{}
			s.zReq(c, reply, hdr, msg, &optz.EventFilterOptions, optz, func() (any, error) {
				if acc, err := extractAccount(subject); err != nil {
					return nil, err
				} else {
					optz.SubszOptions.Subscriptions = true
					optz.SubszOptions.Account = acc
					return s.Subsz(&optz.SubszOptions)
				}
			})
		},
		"CONNZ": func(sub *subscription, c *client, _ *Account, subject, reply string, hdr, msg []byte) {

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Use the canonical system request subject format, e.g. '$SYS.REQ.ACCOUNT.<account-id>.<ENDPOINT>' with all tokens present
  2. Prefer the server's provided request helpers/monitoring client rather than hand-building subjects
  3. Upgrade client monitoring tools to match the server version's system API subjects

Example fix

// before
sub := "$SYS.REQ.ACCOUNT.SUBSZ" // missing account token
// after
sub := "$SYS.REQ.ACCOUNT." + accID + ".SUBSZ"
Defensive patterns

Strategy: type-guard

Validate before calling

func validSysReqSubject(subj string) bool {
    return strings.HasPrefix(subj, "$SYS.REQ.ACCOUNT.") && len(strings.Split(subj, ".")) == 6
}

Type guard

func isMalformedSubjectErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "is malformed")
}

Try / catch

acc, err := extractAccount(subject)
if err != nil {
    // log and drop malformed system request
    return
}

Prevention

When it happens

Trigger: A message published to a $SYS.REQ.ACCOUNT.* service subject with the wrong number of dot-separated tokens, so extractAccount's strings.Split does not yield accReqTokens tokens.

Common situations: Custom tooling publishing handcrafted $SYS request subjects; version mismatches where internal system subject schemas changed between server versions; typos in monitoring scripts.

Understand the failure class

Related errors


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