nats-io/nats-server · error · JSStreamGeneralError

JS_ERR_GENERIC

JS_ERR_GENERIC

Error message

account name can not contain path separators

What it means

A generic JetStream API validation error (JS_ERR_GENERIC) returned by the account purge/delete handler when the account name embedded in the API subject contains path separators ('/' or '\\'). Because account names map to storage directory names, path separators could enable path traversal, so the request is rejected before any purge happens.

Source

Thrown at server/jetstream_api.go:3151

		s.Warnf(badAPIRequestT, msg)
		return
	}
	if acc != s.SystemAccount() {
		return
	}

	js := s.getJetStream()
	if js == nil {
		return
	}

	accName := tokenAt(subject, 5)

	var resp = JSApiAccountPurgeResponse{ApiResponse: ApiResponse{Type: JSApiAccountPurgeResponseType}}

	// Check for path like separators in the name.
	if strings.ContainsAny(accName, `\/`) {
		resp.Error = NewJSStreamGeneralError(errors.New("account name can not contain path separators"))
		s.sendAPIErrResponse(ci, acc, subject, reply, string(msg), s.jsonResponse(&resp))
		return
	}

	if !s.JetStreamIsClustered() {
		var streams []*stream
		var ac *Account
		if ac, err = s.lookupAccount(accName); err == nil && ac != nil {
			streams = ac.streams()
		}

		s.Noticef("Purge request for account %s (streams: %d, hasAccount: %t)",
			accName, len(streams), ac != nil)

		for _, mset := range streams {
			err := mset.delete()
			if err != nil {
				resp.Error = NewJSStreamDeleteError(err)

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Strip or reject path separators from the account name before building the API subject.
  2. Use the account's canonical name (no slashes) when constructing $JS.API subjects.
  3. Sanitize identifiers at the config layer so account names can never contain '/' or '\\'.
  4. If a slash-bearing name is required, use an encoding scheme and decode on your side, not in the subject token.

Example fix

// before
subj := fmt.Sprintf("$JS.API.%s", accName) // accName = "acme/prod"
// after
if strings.ContainsAny(accName, `\/`) {
    return fmt.Errorf("invalid account name %q: path separators not allowed", accName)
}
subj := fmt.Sprintf("$JS.API.%s", accName)
Defensive patterns

Strategy: validation

Validate before calling

func validAccountName(name string) bool {
    return name != "" && !strings.ContainsAny(name, `\/`)
}
if !validAccountName(accName) { return fmt.Errorf("invalid account name %q", accName) }

Try / catch

if err := purgeAccount(nc, accName); err != nil {
    if strings.Contains(err.Error(), "path separators") {
        return fmt.Errorf("account name %q contains path separators", accName)
    }
    return err
}

Prevention

When it happens

Trigger: Sending $JS.API.ACCOUNT.PURGE (or similar account-scoped request) where token 5 of the subject (the account name) contains '/' or '\\', detected via strings.ContainsAny(accName, `\\/`).

Common situations: Passing a full account path or mis-split subject token as the account name; building API subjects by string concatenation with unsanitized account identifiers; automation that includes slashes in tenant/account names.

Related errors


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