{"record":{"id":"459cfc8fc5fe3dce","repo":"grpc/grpc-java","slug":"the-lookupservice-field-is-not-valid-uri-lookup","errorCode":null,"errorMessage":"The lookupService field is not valid URI: ${lookupService}","messagePattern":"The lookupService field is not valid URI: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"rls/src/main/java/io/grpc/rls/RlsProtoConverters.java","lineNumber":149,"sourceCode":"        Set<String> keys = new HashSet<>();\n        for (NameMatcher header : keyBuilder.headers()) {\n          checkKeys(keys, header.key(), \"header\");\n        }\n        for (String key : keyBuilder.constantKeys().keySet()) {\n          checkKeys(keys, key, \"constant\");\n        }\n        String extraKeyStr = keyToString(keyBuilder.extraKeys());\n        checkArgument(keys.add(extraKeyStr),\n            \"duplicate extra key in grpc_keybuilders: \" + extraKeyStr);\n      }\n\n      // Validate lookup_service\n      String lookupService = JsonUtil.getString(json, \"lookupService\");\n      checkArgument(!Strings.isNullOrEmpty(lookupService), \"lookupService must not be empty\");\n      try {\n        URI unused = new URI(lookupService);\n      } catch (URISyntaxException e) {\n        throw new IllegalArgumentException(\n            \"The lookupService field is not valid URI: \" + lookupService, e);\n      }\n      long timeout = orDefault(\n          JsonUtil.getStringAsDuration(json, \"lookupServiceTimeout\"),\n          DEFAULT_LOOKUP_SERVICE_TIMEOUT);\n      checkArgument(timeout > 0, \"lookupServiceTimeout should be positive\");\n      Long maxAge = JsonUtil.getStringAsDuration(json, \"maxAge\");\n      Long staleAge = JsonUtil.getStringAsDuration(json, \"staleAge\");\n      if (maxAge == null) {\n        checkArgument(staleAge == null, \"to specify staleAge, must have maxAge\");\n        maxAge = MAX_AGE_NANOS;\n      }\n      // If staleAge is not set, clamp maxAge to <= 5.\n      if (staleAge == null && maxAge > MAX_AGE_NANOS) {\n        maxAge = MAX_AGE_NANOS;\n      }\n      // Clamp staleAge to <= 5\n      if (staleAge == null || staleAge > MAX_AGE_NANOS) {","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/grpc/grpc-java/blob/64daddc1f3d1975670f769f3e97bde8b2ba32d25/rls/src/main/java/io/grpc/rls/RlsProtoConverters.java#L131-L167","documentation":"When converting the RLS (Route Lookup Service) LB policy JSON config, the 'lookupService' field must parse as a valid URI. This IllegalArgumentException is thrown from the config conversion when new URI(lookupService) raises URISyntaxException, i.e. the configured lookup service address is not a syntactically valid URI.","triggerScenarios":"Providing a service config (LoadBalancingConfig) for the rls LB policy where 'lookupService' is a malformed URI — missing scheme, illegal characters, unbalanced brackets in an IPv6 literal, spaces, or a scheme like 'localhost:50051' interpreted as scheme-only.","commonSituations":"Hand-writing gRPC service config JSON with an RLS policy, forgetting 'http://' or 'https://' prefix, typos in the host, or copy-pasting a target string with whitespace or quotes into the config.","solutions":["Correct the 'lookupService' value in the service config to a fully qualified, valid URI such as 'https://rls.example.com:443'.","Validate the URI in advance: new URI(value) in a test or startup check to reproduce the URISyntaxException before deploying.","Quote/escape special characters and remove whitespace; wrap bare IPv6 hosts in brackets, e.g. 'http://[::1]:50051'.","Ensure the value is a non-empty string (empty values are rejected earlier with a different message)."],"exampleFix":"// before\n{\"rlsExperiments\": {\"lookupService\": \"rls.example.com:443\"}}\n// after\n{\"rlsExperiments\": {\"lookupService\": \"https://rls.example.com:443\"}}","handlingStrategy":"validation","validationCode":"static void validateLookupService(String uri) {\n  try {\n    new URI(uri);\n  } catch (URISyntaxException e) {\n    throw new IllegalArgumentException(\"invalid lookupService: \" + uri, e);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include scheme and authority: https://host[:port].","Run service-config JSON through a startup validator before registering the LB policy.","Avoid hand-editing configs in production; template them with validation.","Remember bare host:port strings are not valid URIs — 'localhost:50051' parses as scheme-only."],"tags":["grpc","rls","config","uri"],"backgroundTag":"invalid-url-format","analyzedSha":"64daddc1f3d1975670f769f3e97bde8b2ba32d25","analyzedAt":"2026-09-08T06:14:57.704Z","contentChangedAt":"2026-09-08T06:14:57.704Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}