{"record":{"id":"fb3056ebd43c3c7a","repo":"nats-io/nats-server","slug":"sort-by-reason-only-valid-on-closed-connections","errorCode":null,"errorMessage":"sort by reason only valid on closed connections","messagePattern":"sort by reason only valid on closed connections","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"server/monitor.go","lineNumber":256,"sourceCode":"\t\tsubsDet = opts.SubscriptionsDetail\n\t\toffset = opts.Offset\n\t\tif offset < 0 {\n\t\t\toffset = 0\n\t\t}\n\t\tlimit = opts.Limit\n\t\tif limit <= 0 {\n\t\t\tlimit = DefaultConnListSize\n\t\t}\n\t\t// state\n\t\tstate = opts.State\n\n\t\t// ByStop only makes sense on closed connections\n\t\tif sortOpt == ByStop && state != ConnClosed {\n\t\t\treturn nil, fmt.Errorf(\"sort by stop only valid on closed connections\")\n\t\t}\n\t\t// ByReason is the same.\n\t\tif sortOpt == ByReason && state != ConnClosed {\n\t\t\treturn nil, fmt.Errorf(\"sort by reason only valid on closed connections\")\n\t\t}\n\t\t// If searching by CID\n\t\tif opts.CID > 0 {\n\t\t\tcid = opts.CID\n\t\t\tlimit = 1\n\t\t}\n\t\t// If filtering by subject.\n\t\tif opts.FilterSubject != _EMPTY_ && opts.FilterSubject != fwcs {\n\t\t\tif acc == _EMPTY_ {\n\t\t\t\treturn nil, fmt.Errorf(\"filter by subject only valid with account filtering\")\n\t\t\t}\n\t\t\tfilter = opts.FilterSubject\n\t\t}\n\t}\n\n\tc := &Connz{\n\t\tOffset: offset,\n\t\tLimit:  limit,","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/monitor.go#L238-L274","documentation":"Connz returns this when you request sorting by ByReason (or ByStop) while the state filter is not ConnClosed. Stop time and close reason are only recorded for closed connections, so sorting on them for open/all connections is meaningless and rejected.","triggerScenarios":"Calling Connz with SortOpt=ByReason (or ByStop) while opts.State is ConnAll, ConnOpen, or left unset; hitting the /connz monitoring endpoint with sort=reason but without state=closed.","commonSituations":"Building monitoring dashboards that list connection disconnect reasons; after upgrading the nats-server monitoring API and enabling the newer ByReason sort; testing monitor endpoints (TestMonitorConnzSortedByReasonOnOpen exercises exactly this rejection).","solutions":["Pass ByClosed (ConnClosed) state together with ByReason: Connz(&ConnzOptions{State: ConnClosed, SortOpt: ByReason})","If you need open connections, drop the ByReason sort and use the default sort instead","On the HTTP endpoint, request /connz?state=closed&sort=reason"],"exampleFix":"// before\nconnz, err := s.Connz(&server.ConnzOptions{SortOpt: server.ByReason})\n// after\nconnz, err := s.Connz(&server.ConnzOptions{State: server.ConnClosed, SortOpt: server.ByReason})","handlingStrategy":"validation","validationCode":"func validConnzOpts(o *server.ConnzOptions) bool {\n\tif o.SortOpt == server.ByReason || o.SortOpt == server.ByStop {\n\t\treturn o.State == server.ConnClosed\n\t}\n\treturn true\n}","typeGuard":null,"tryCatchPattern":"cz, err := srv.Connz(opts)\nif err != nil {\n\tif strings.Contains(err.Error(), \"only valid on closed connections\") {\n\t\topts.State = server.ConnClosed\n\t\tcz, err = srv.Connz(opts)\n\t}\n}","preventionTips":["Always pair ByReason/ByStop sorts with State: ConnClosed","Add a unit test for monitor option combinations you expose in tooling","Default State explicitly instead of relying on zero values"],"tags":["monitoring","connz","invalid-options"],"backgroundTag":"invalid-monitoring-query-options","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}