{"record":{"id":"4015ad82d73fd846","repo":"nats-io/nats-server","slug":"subject-has-exceeded-number-of-tokens-limit","errorCode":null,"errorMessage":"subject has exceeded number of tokens limit","messagePattern":"subject has exceeded number of tokens limit","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/errors.go","lineNumber":79,"sourceCode":"\tErrBadClientProtocol = errors.New(\"invalid client protocol\")\n\n\t// ErrTooManyConnections signals a client that the maximum number of connections supported by the\n\t// server has been reached.\n\tErrTooManyConnections = errors.New(\"maximum connections exceeded\")\n\n\t// ErrTooManyAccountConnections signals that an account has reached its maximum number of active\n\t// connections.\n\tErrTooManyAccountConnections = errors.New(\"maximum account active connections exceeded\")\n\n\t// ErrLeafNodeLoop signals a leafnode is trying to register for a cluster we already have registered.\n\tErrLeafNodeLoop = errors.New(\"leafnode loop detected\")\n\n\t// ErrTooManySubs signals a client that the maximum number of subscriptions per connection\n\t// has been reached.\n\tErrTooManySubs = errors.New(\"maximum subscriptions exceeded\")\n\n\t// ErrTooManySubTokens signals a client that the subject has too many tokens.\n\tErrTooManySubTokens = errors.New(\"subject has exceeded number of tokens limit\")\n\n\t// ErrClientConnectedToRoutePort represents an error condition when a client\n\t// attempted to connect to the route listen port.\n\tErrClientConnectedToRoutePort = errors.New(\"attempted to connect to route port\")\n\n\t// ErrClientConnectedToLeafNodePort represents an error condition when a client\n\t// attempted to connect to the leaf node listen port.\n\tErrClientConnectedToLeafNodePort = errors.New(\"attempted to connect to leaf node port\")\n\n\t// ErrLeafNodeHasSameClusterName represents an error condition when a leafnode is a cluster\n\t// and it has the same cluster name as the hub cluster.\n\tErrLeafNodeHasSameClusterName = errors.New(\"remote leafnode has same cluster name\")\n\n\t// ErrLeafNodeDisabled is when we disable leafnodes.\n\tErrLeafNodeDisabled = errors.New(\"leafnodes disabled\")\n\n\t// ErrConnectedToWrongPort represents an error condition when a connection is attempted\n\t// to the wrong listen port (for instance a LeafNode to a client port, etc...)","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/errors.go#L61-L97","documentation":"ErrTooManySubTokens means a subscription subject has more tokens (dot-separated segments) than the server's max_subject_tokens limit (or fewer than the minimum). The NATS server enforces this at SUBSCRIBE time to reject subjects that are structurally invalid or suspiciously deep, protecting subject-based routing tables from abuse. It is returned to the client from the SUB/subscription processing path in client.go.","triggerScenarios":"Calling a SUBSCRIBE API (client.subscribe / nc.Subscribe) with a subject whose token count exceeds the server's max_subject_tokens config, e.g. subscribing to 'a.b.c.d.e.f...' with more tokens than allowed. Also triggered when the subject has too few tokens for a wildcard position in some configurations.","commonSituations":"Mistakenly passing a payload or reply subject with many dot-separated segments as a subscription subject; misconfigured max_subject_tokens (very low value) in server config; generating subjects programmatically by joining user data with dots (e.g. paths) producing excessive tokens.","solutions":["Reduce the number of tokens in the subscription subject by flattening or shortening it","Raise max_subject_tokens in the server's configuration and reload/restart the server","Check the code that builds the subject string for accidental joining of too many segments","Validate subject token count client-side before subscribing"],"exampleFix":"// before\nnc.Subscribe(strings.Join(parts, \".\"), handler) // parts may be huge\n// after\nif len(strings.Split(subject, \".\")) > 10 { subject = flattenSubject(subject) }\nnc.Subscribe(subject, handler)","handlingStrategy":"validation","validationCode":"func subjectTokenCount(subject string) int { return len(strings.Split(subject, \".\")) }\nif n := subjectTokenCount(subj); n < 1 || n > 10 { return fmt.Errorf(\"subject %q has %d tokens, exceeds limit\", subj, n) }","typeGuard":"func isSubjectWithinLimit(subject string, max int) bool {\n    return subject != \"\" && len(strings.Split(subject, \".\")) <= max\n}","tryCatchPattern":"_, err := nc.Subscribe(subj, handler)\nif errors.Is(err, nats.ErrBadSubject) || strings.Contains(err.Error(), \"tokens limit\") {\n    // flatten subject or raise server max_subject_tokens\n}","preventionTips":["Validate generated subjects' token count before subscribing","Keep subject hierarchies shallow; encode attributes as values not extra tokens","Set a sane max_subject_tokens in server config and document it"],"tags":["nats","subject","subscription","configuration"],"backgroundTag":"subject-token-limit-exceeded","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}