{"record":{"id":"7b785ce1b4c226e2","repo":"nats-io/nats-server","slug":"subject-q-is-not-a-valid-subject","errorCode":null,"errorMessage":"subject %q is not a valid subject","messagePattern":"subject %q is not a valid subject","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/opts.go","lineNumber":5056,"sourceCode":"\t\t\t\tcontinue\n\t\t\t}\n\t\t\tp.Deny = subjects\n\t\tdefault:\n\t\t\tif !tk.IsUsedVariable() {\n\t\t\t\terr := &configErr{tk, fmt.Sprintf(\"Unknown field name %q parsing subject permissions, only 'allow' or 'deny' are permitted\", k)}\n\t\t\t\t*errors = append(*errors, err)\n\t\t\t}\n\t\t}\n\t}\n\treturn p, nil\n}\n\n// Helper function to validate permissions subjects.\nfunc checkPermSubjectArray(sa []string, allowQueue bool) error {\n\tfor _, s := range sa {\n\t\tif !IsValidSubject(s) {\n\t\t\tif !allowQueue {\n\t\t\t\treturn fmt.Errorf(\"subject %q is not a valid subject\", s)\n\t\t\t}\n\t\t\t// Check here if this is a queue group qualified subject.\n\t\t\telements := strings.Fields(s)\n\t\t\tif len(elements) != 2 {\n\t\t\t\treturn fmt.Errorf(\"subject %q is not a valid subject\", s)\n\t\t\t} else if !IsValidSubject(elements[0]) {\n\t\t\t\treturn fmt.Errorf(\"subject %q is not a valid subject\", elements[0])\n\t\t\t} else if !IsValidSubject(elements[1]) {\n\t\t\t\treturn fmt.Errorf(\"queue %q is not a valid queue\", elements[1])\n\t\t\t}\n\t\t}\n\t}\n\treturn nil\n}\n\n// PrintTLSHelpAndDie prints TLS usage and exits.\nfunc PrintTLSHelpAndDie() {\n\tfmt.Printf(\"%s\", tlsUsage)","sourceCodeStart":5038,"sourceCodeEnd":5074,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/opts.go#L5038-L5074","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Correct the subject printed in the error to a valid NATS subject (tokens of alphanumerics/underscore, '*' per token, '>' only last)","Quote subjects in YAML so spaces are not injected","Remove empty entries from the array","Use a queue-permission context (with queue names) only where queue subjects are permitted"],"exampleFix":"// before\nallow: [\"foo bar\"]\n// after\nallow: [\"foo.bar\"]","handlingStrategy":"validation","validationCode":"for _, s := range subjects {\n\tif !server.IsValidSubject(s) {\n\t\treturn fmt.Errorf(\"bad permission subject %q\", s)\n\t}\n}","typeGuard":"func isPermSubject(s string) bool { return IsValidSubject(s) }","tryCatchPattern":"if err := server.ProcessConfigFile(path); err != nil {\n\tvar subjErr *SubjectErr // or string match on 'not a valid subject'\n\tif strings.Contains(err.Error(), \"not a valid subject\") {\n\t\tlog.Fatalf(\"fix subject in config: %v\", err)\n\t}\n}","preventionTips":["Quote all subject strings in YAML to prevent token splitting","Validate subjects when generating config","Only use '*' per token and '>' as final token"],"tags":["config","permissions","subjects"],"backgroundTag":"invalid-subject","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}