nats-io/nats-server · error

parse error: '%s'

Error message

parse error: '%s'

What it means

parseUnsubProto validates the argument count of an inbound UNSUB protocol line from a remote (route/leaf) connection: after the subject (and optional account/origin), only an optional queue name may follow. Any additional fields make the line unparseable and the server returns this generic 'parse error'.

Source

Thrown at server/route.go:1404

		subjIdx     int
	)
	// If `hasOrigin` is true, then it means this is a LS- with origin in proto.
	if hasOrigin {
		// We would not be here if there was not at least 1 field.
		origin = args[0]
		subjIdx = 1
	}
	// If there is an account in the protocol, bump the subject index.
	if accInProto {
		subjIdx++
	}

	switch len(args) {
	case subjIdx + 1:
	case subjIdx + 2:
		queue = args[subjIdx+1]
	default:
		return nil, _EMPTY_, nil, nil, fmt.Errorf("parse error: '%s'", arg)
	}
	if accInProto {
		// If there is an account in the protocol, it is before the subject.
		accountName = string(args[subjIdx-1])
	}
	return origin, accountName, args[subjIdx], queue, nil
}

// Indicates no more interest in the given account/subject for the remote side.
func (c *client) processRemoteUnsub(arg []byte, leafUnsub bool) (err error) {
	srv := c.srv
	if srv == nil {
		return nil
	}

	var accountName string
	// Assume the account will be in the protocol.
	accInProto := true

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Emit UNSUB as 'UNSUB <sid>[ <maxmsgs>]' with no extra fields on remote links
  2. Update the leaf/route peer client or bridge to a spec-compliant version
  3. Enable trace logging to capture the offending UNSUB line
  4. Verify account/origin sentinel placement matches the negotiated protocol features

Example fix

// before (bridge)
"UNSUB sid 1 extra\r\n"
// after
"UNSUB sid 1\r\n"
Defensive patterns

Strategy: validation

Validate before calling

// Validate UNSUB line shape before forwarding on a remote link
parts := strings.Fields(line)
if len(parts) > 3 { // UNSUB sid [maxmsgs] plus optional queue per remote protocol
    return fmt.Errorf("too many fields in remote UNSUB: %v", parts)
}

Prevention

When it happens

Trigger: UNSUB line with too many fields, e.g. 'UNSUB <sid> <maxmsgs> <extra>' when forwarded remotely, or a subject+queue plus unexpected extra tokens.

Common situations: Leaf/route connections from third-party or older implementations that append extra fields to UNSUB, protocol translation bugs in bridges, or corrupted frames.

Understand the failure class

Related errors


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