{"record":{"id":"ab22411811fbc05e","repo":"nats-io/nats-server","slug":"trusted-operators-or-trusted-keys-configuration-is","errorCode":null,"errorMessage":"trusted operators or trusted keys configuration is required for JWT authentication via cookie %q","messagePattern":"trusted operators or trusted keys configuration is required for JWT authentication via cookie %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/websocket.go","lineNumber":1171,"sourceCode":"\t// the user to be present.\n\tif wo.NoAuthUser != _EMPTY_ {\n\t\tif err := validateNoAuthUser(o, wo.NoAuthUser); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\t// Token/Username not possible if there are users/nkeys\n\tif len(o.Users) > 0 || len(o.Nkeys) > 0 {\n\t\tif wo.Username != _EMPTY_ {\n\t\t\treturn fmt.Errorf(\"websocket authentication username not compatible with presence of users/nkeys\")\n\t\t}\n\t\tif wo.Token != _EMPTY_ {\n\t\t\treturn fmt.Errorf(\"websocket authentication token not compatible with presence of users/nkeys\")\n\t\t}\n\t}\n\t// Using JWT requires Trusted Keys\n\tif wo.JWTCookie != _EMPTY_ {\n\t\tif len(o.TrustedOperators) == 0 && len(o.TrustedKeys) == 0 {\n\t\t\treturn fmt.Errorf(\"trusted operators or trusted keys configuration is required for JWT authentication via cookie %q\", wo.JWTCookie)\n\t\t}\n\t}\n\tif err := validatePinnedCerts(wo.TLSPinnedCerts); err != nil {\n\t\treturn fmt.Errorf(\"websocket: %v\", err)\n\t}\n\n\t// Check for invalid headers here.\n\tfor key := range wo.Headers {\n\t\tk := strings.ToLower(key)\n\t\tswitch k {\n\t\tcase \"host\",\n\t\t\t\"content-length\",\n\t\t\t\"connection\",\n\t\t\t\"upgrade\",\n\t\t\t\"nats-no-masking\":\n\t\t\treturn fmt.Errorf(\"websocket: invalid header %q not allowed\", key)\n\t\t}\n","sourceCodeStart":1153,"sourceCodeEnd":1189,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/websocket.go#L1153-L1189","documentation":"JWT-based websocket authentication (websocket.jwt_cookie) requires the server to trust decentralized auth: either trusted operator claims (TrustedOperators) or explicit trusted public NKeys (TrustedKeys). Without one of these, JWTs in the cookie cannot be verified, so the validator refuses to start.","triggerScenarios":"Setting websocket { jwt_cookie: \"...\" } in a config that has no operator JWT file and no trusted_keys entries.","commonSituations":"Enabling decentralized JWT auth on a standalone server that was set up without operators; forgetting to sync trusted keys after operator rotation.","solutions":["Add the operator JWT via the operator or resolver config so TrustedOperators is populated","Or add trusted_keys with the operator/signing account public keys to the config","Or remove jwt_cookie if JWT auth is not intended"],"exampleFix":"// before\nwebsocket { jwt_cookie: \"nats_jwt\" }\n// after\noperator: ./operator.jwt\nresolver: MEMORY\nwebsocket { jwt_cookie: \"nats_jwt\" }","handlingStrategy":"validation","validationCode":"if opts.Websocket.JWTCookie != \"\" && len(opts.TrustedOperators) == 0 && len(opts.TrustedKeys) == 0 {\n  return fmt.Errorf(\"jwt_cookie requires trusted operators or trusted keys\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pair every jwt_cookie setting with operator JWT or trusted_keys in the same config review","Keep operator/trusted keys in version-controlled config templates"],"tags":["websocket","jwt","config-validation"],"backgroundTag":"missing-trusted-operator","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}