nats-io/nats-server · error
publish deny: %w
Error message
publish deny: %w
What it means
Validation of a permission's publish deny list failed. This library wraps the underlying subject-array validation error with the 'publish deny' prefix to indicate that the DENY subjects of the Publish permission block are malformed (e.g. invalid wildcard usage or empty subject). It is thrown while validating authorization blocks, users/nkeys permissions, or account-scoped permission structures at server startup or config reload.
Source
Thrown at server/auth.go:1738
return err
}
if err := validatePermissionSubjects(u.Permissions); err != nil {
return fmt.Errorf("invalid permissions for nkey %q: %w", u.Nkey, err)
}
}
return validateNoAuthUser(o, o.NoAuthUser)
}
func validatePermissionSubjects(p *Permissions) error {
if p == nil {
return nil
}
if p.Publish != nil {
if err := checkPermSubjectArray(p.Publish.Allow, false); err != nil {
return fmt.Errorf("publish allow: %w", err)
}
if err := checkPermSubjectArray(p.Publish.Deny, false); err != nil {
return fmt.Errorf("publish deny: %w", err)
}
}
if p.Subscribe != nil {
if err := checkPermSubjectArray(p.Subscribe.Allow, true); err != nil {
return fmt.Errorf("subscribe allow: %w", err)
}
if err := checkPermSubjectArray(p.Subscribe.Deny, true); err != nil {
return fmt.Errorf("subscribe deny: %w", err)
}
}
return nil
}
func validateAllowedConnectionTypes(m map[string]struct{}) error {
for ct := range m {
ctuc := strings.ToUpper(ct)
switch ctuc {
case jwt.ConnectionTypeStandard, jwt.ConnectionTypeWebsocket,View on GitHub (pinned to 3a66a489d2)
Solutions
- Fix the offending subject in the Publish.Deny list — the wrapped error names the exact invalid subject.
- Run nats-server --signal reload or start with -V/trace logging to see the wrapped subject detail.
- Remove empty strings and duplicate entries from the deny array.
- Validate subject syntax rules: tokens separated by '.', wildcards '*' (one token) and '>' (tail only).
Example fix
// before
perms := server.Permissions{Publish: {Deny: []string{"foo.**", ""}}}
// after
perms := server.Permissions{Publish: {Deny: []string{"foo.bar", "foo.>"}}} Defensive patterns
Strategy: validation
Validate before calling
for i, s := range perm.Publish.Deny {
if s == "" || strings.Contains(s, " ") {
return fmt.Errorf("invalid publish deny subject at %d: %q", i, s)
}
} Type guard
func validSubject(s string) bool {
if s == "" { return false }
for i, t := range strings.Split(s, ".") {
if t == "" || t == ">" && i != len(strings.Split(s, "."))-1 { return false }
}
return true
} Try / catch
if err := validatePermissions(perms, true); err != nil {
if strings.HasPrefix(err.Error(), "publish deny") {
log.Fatalf("fix Publish.Deny subjects: %v", err)
}
} Prevention
- Lint config with `nats-server -t` before every deploy
- Reject empty/whitespace subjects at permission-build time
- Use nats.go subject validation helpers when constructing permissions
- Cover permission generation with unit tests
When it happens
Trigger: Calling validatePermissions (or config validation) with a Permissions struct whose Publish.Deny array contains invalid subjects — e.g. wildcards in illegal positions, tokens exceeding token limits, or subjects with invalid characters. Any []string passed to checkPermSubjectArray(Publish.Deny, false) that fails validation.
Common situations: Typos in nats_server.conf authorization block deny: lists, programmatically built Permissions withSubjects like 'foo.>' nested inside another wildcard, or empty-string entries in the deny array. Often surfaces during server startup after editing the authorization section or when generating users via code/tools.
Related errors
- subscribe allow: %w
- subscribe deny: %w
- invalid connection types %q
- max_ack_pending must be set to -1
- bad sampling percentage, should be 1-100
AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02).
Data as JSON: /api/errors/a839978df392ebf9.
Report an issue: GitHub.