nats-io/nats-server · error

subject %q is not a valid subject

Error message

subject %q is not a valid subject

What it means

checkPermSubjectArray() iterates permission subject arrays and requires each entry to pass IsValidSubject. When the array is not queue-qualified (allowQueue=false), the first invalid subject aborts with 'subject %q is not a valid subject', naming the offending entry.

Source

Thrown at server/opts.go:5056

				continue
			}
			p.Deny = subjects
		default:
			if !tk.IsUsedVariable() {
				err := &configErr{tk, fmt.Sprintf("Unknown field name %q parsing subject permissions, only 'allow' or 'deny' are permitted", k)}
				*errors = append(*errors, err)
			}
		}
	}
	return p, nil
}

// Helper function to validate permissions subjects.
func checkPermSubjectArray(sa []string, allowQueue bool) error {
	for _, s := range sa {
		if !IsValidSubject(s) {
			if !allowQueue {
				return fmt.Errorf("subject %q is not a valid subject", s)
			}
			// Check here if this is a queue group qualified subject.
			elements := strings.Fields(s)
			if len(elements) != 2 {
				return fmt.Errorf("subject %q is not a valid subject", s)
			} else if !IsValidSubject(elements[0]) {
				return fmt.Errorf("subject %q is not a valid subject", elements[0])
			} else if !IsValidSubject(elements[1]) {
				return fmt.Errorf("queue %q is not a valid queue", elements[1])
			}
		}
	}
	return nil
}

// PrintTLSHelpAndDie prints TLS usage and exits.
func PrintTLSHelpAndDie() {
	fmt.Printf("%s", tlsUsage)

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Correct the subject printed in the error to a valid NATS subject (tokens of alphanumerics/underscore, '*' per token, '>' only last)
  2. Quote subjects in YAML so spaces are not injected
  3. Remove empty entries from the array
  4. Use a queue-permission context (with queue names) only where queue subjects are permitted

Example fix

// before
allow: ["foo bar"]
// after
allow: ["foo.bar"]
Defensive patterns

Strategy: validation

Validate before calling

for _, s := range subjects {
	if !server.IsValidSubject(s) {
		return fmt.Errorf("bad permission subject %q", s)
	}
}

Type guard

func isPermSubject(s string) bool { return IsValidSubject(s) }

Try / catch

if err := server.ProcessConfigFile(path); err != nil {
	var subjErr *SubjectErr // or string match on 'not a valid subject'
	if strings.Contains(err.Error(), "not a valid subject") {
		log.Fatalf("fix subject in config: %v", err)
	}
}

Prevention

When it happens

Trigger: Any permissions allow/deny array (publish/subscribe) containing a subject that fails NATS subject rules — e.g. 'foo bar' in a non-queue array, empty string, token with illegal characters like '-' or '@', or misplaced wildcards.

Common situations: Copy-pasted subjects with trailing spaces; queue-group syntax ("subj queue") pasted into a plain permissions array; using characters outside the allowed set; YAML folding turning a subject into multiple tokens.

Related errors


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