nats-io/nats-server · error

invalid domain name: derived %q is not a valid subject

Error message

invalid domain name: derived %q is not a valid subject

What it means

The server-wide `jetstream_domain` option (o.JetStreamDomain) is also embedded into an API subject via jsDomainAPI and must therefore yield a valid NATS subject. Validation happens before the stricter character check, so this error fires first for domains that break subject syntax (invalid characters, empty tokens, bad wildcards).

Source

Thrown at server/jetstream.go:2929

		for a, d := range o.JsAccDefaultDomain {
			sacc := DEFAULT_SYSTEM_ACCOUNT
			if o.SystemAccount != _EMPTY_ {
				sacc = o.SystemAccount
			}
			if a == sacc {
				return fmt.Errorf("system account %q can not be in default_js_domain", a)
			}
			if d == _EMPTY_ {
				continue
			}
			if sub := fmt.Sprintf(jsDomainAPI, d); !IsValidSubject(sub) {
				return fmt.Errorf("default_js_domain contains account %q with invalid domain name %q", a, d)
			}
		}
	}
	if o.JetStreamDomain != _EMPTY_ {
		if subj := fmt.Sprintf(jsDomainAPI, o.JetStreamDomain); !IsValidSubject(subj) {
			return fmt.Errorf("invalid domain name: derived %q is not a valid subject", subj)
		}

		if !isValidName(o.JetStreamDomain) {
			return fmt.Errorf("invalid domain name: may not contain ., * or >")
		}
	}
	// If not clustered no checks needed past here.
	if !o.JetStream || o.Cluster.Port == 0 {
		return nil
	}
	if o.ServerName == _EMPTY_ {
		return fmt.Errorf("jetstream cluster requires `server_name` to be set")
	}
	if o.Cluster.Name == _EMPTY_ {
		return fmt.Errorf("jetstream cluster requires `cluster.name` to be set")
	}

	h := strings.ToLower(o.JetStreamExtHint)

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Correct `jetstream_domain` so the derived subject is valid: use only alphanumeric, underscore, hyphen and dot characters, with no spaces or empty segments.
  2. Remove the `jetstream_domain` option if a single default domain is intended.
  3. Restart the server to re-run validation.

Example fix

// before
jetstream_domain: ".foo."
// after
jetstream_domain: "foo"
Defensive patterns

Strategy: validation

Validate before calling

if cfg.JetStreamDomain != "" {
    sub := "$JS." + cfg.JetStreamDomain + ".API"
    if !nats.IsValidSubject(sub) {
        return fmt.Errorf("jetstream_domain %q derives invalid subject", cfg.JetStreamDomain)
    }
}

Prevention

When it happens

Trigger: Configuring `jetstream_domain` in the server config with a value where fmt.Sprintf(jsDomainAPI, domain) is not a valid subject — e.g. containing spaces, leading/trailing dots, or invalid characters.

Common situations: Misconfigured multi-domain setups; environment-specific config templating injecting an empty or whitespace-padded domain; using reserved wildcard characters in the domain.

Related errors


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