{"record":{"id":"e953186fd41bec1f","repo":"apache/druid","slug":"the-grpc-query-server-requires-either-a-basic-or-a","errorCode":null,"errorMessage":"The gRPC query server requires either a Basic or Anonymous authorizer: it does not work with others yet.","messagePattern":"The gRPC query server requires either a Basic or Anonymous authorizer: it does not work with others yet\\.","errorType":"exception","errorClass":"UOE","httpStatus":null,"severity":"critical","filePath":"extensions-contrib/grpc-query/src/main/java/org/apache/druid/grpc/server/QueryServer.java","lineNumber":118,"sourceCode":"      // BasicHTTPAuthenticator is not visible here.\n      if (\"BasicHTTPAuthenticator\".equals(authenticator.getClass().getSimpleName())) {\n        log.info(\"Using Basic authentication\");\n        return new BasicAuthServerInterceptor(authenticator);\n      }\n    }\n\n    // Otherwise, look for an Anonymous authenticator\n    for (Authenticator authenticator : authMapper.getAuthenticatorChain()) {\n      if (authenticator instanceof AnonymousAuthenticator || authenticator instanceof AllowAllAuthenticator) {\n        log.info(\"Using Anonymous authentication\");\n        return new AnonymousAuthServerInterceptor(authenticator);\n      }\n    }\n\n    // gRPC does not support other forms of authenticators yet.\n    String msg = \"The gRPC query server requires either a Basic or Anonymous authorizer: it does not work with others yet.\";\n    log.error(msg);\n    throw new UOE(msg);\n  }\n\n  public void stop() throws InterruptedException\n  {\n    if (server != null) {\n      log.info(\"Server stopping\");\n      healthService.unregisterService(QueryService.class.getSimpleName());\n      healthService.unregisterService(\"\");\n      server.shutdown().awaitTermination(30, TimeUnit.SECONDS);\n    }\n  }\n\n  /**\n   * Await termination on the main thread since the grpc library uses daemon threads.\n   */\n  public void blockUntilShutdown() throws InterruptedException\n  {\n    if (server != null) {","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/grpc-query/src/main/java/org/apache/druid/grpc/server/QueryServer.java#L100-L136","documentation":"At server startup, QueryServer.makeSecurityInterceptor inspects the configured authenticator/authorizer chain. The gRPC extension only knows how to build its security interceptor for Basic auth or the Anonymous authenticator; any other authenticator type reaches the fall-through code, logs the message, and throws UOE(\"The gRPC query server requires either a Basic or Anonymous authorizer: ...\"), preventing the server from starting.","triggerScenarios":"Starting a Druid process with the gRPC query extension enabled while the authenticators list contains only non-Basic authenticators (e.g. JWT, Kerberos, or an empty chain without anonymous), so the interceptor factory cannot select a Basic or Anonymous authenticator.","commonSituations":"Copying the auth config from a cluster secured with Kerberos/JWT into a gRPC-enabled node; forgetting to configure druid.auth.authenticators at all (no Anonymous authenticator defined); extension version predates support for other authenticator types.","solutions":["Configure a basic authenticator in druid.auth.authenticators for the gRPC-enabled process, e.g. {\"name\":\"basic\",\"type\":\"basic\"}.","Alternatively configure the anonymous authenticator ({\"name\":\"anonymous\",\"type\":\"anonymous\"}) for unsecured/dev setups.","Remove or reorder the authenticator chain so a Basic or Anonymous authenticator is present and usable by the gRPC server.","Check the extension version/docs for whether newer releases support your authenticator type before attempting custom changes."],"exampleFix":"// before: druid.auth.authenticators=[{\"name\":\"kerberos\",\"type\":\"kerberos\"}]\n// after\ndruid.auth.authenticators=[{\"name\":\"basic\",\"type\":\"basic\"}, {\"name\":\"anonymous\",\"type\":\"anonymous\"}]","handlingStrategy":"validation","validationCode":"// Pre-flight: verify config includes a basic or anonymous authenticator before starting\nObject[] auths = props.get(\"druid.auth.authenticators\");\nboolean ok = Arrays.stream(auths).anyMatch(a -> \"basic\".equals(a.type) || \"anonymous\".equals(a.type));\nif (!ok) throw new IllegalStateException(\"gRPC server needs a Basic or Anonymous authenticator\");","typeGuard":null,"tryCatchPattern":"try {\n  queryServer.start();\n} catch (UnsupportedOperationException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Basic or Anonymous authorizer\")) {\n    throw new IllegalStateException(\"Fix druid.auth.authenticators: add {name:basic,type:basic} or anonymous\", e);\n  }\n  throw e;\n}","preventionTips":["Always configure a basic or anonymous authenticator on nodes running the gRPC extension.","Validate the full runtime.properties auth chain in config CI before deploy.","Do not copy Kerberos/JWT-only auth configs onto gRPC-enabled nodes.","Check the extension docs for supported authenticator types per release."],"tags":["grpc","authentication","startup","configuration"],"backgroundTag":"invalid-config-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}