{"record":{"id":"630a4203c3407e6c","repo":"apache/druid","slug":"call-returned-null-ip-for-s-skipping","errorCode":null,"errorMessage":"Call returned null IP for %s, skipping","messagePattern":"Call returned null IP for (.+?), skipping","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"extensions-contrib/gce-extensions/src/main/java/org/apache/druid/indexing/overlord/autoscaling/gce/GceAutoScaler.java","lineNumber":479,"sourceCode":"      List<String> instanceIps = new ArrayList<>();\n      InstanceList response;\n      do {\n        response = request.execute();\n        if (response.getItems() == null) {\n          continue;\n        }\n        for (Instance instance : response.getItems()) {\n          // Assuming that every server has at least one network interface...\n          String ip = instance.getNetworkInterfaces().get(0).getNetworkIP();\n          // ...even though some IPs are reported as null on the spot but later they are ok,\n          // so we skip the ones that are null. fear not, they are picked up later this just\n          // prevents to have a machine called 'null' around which makes the caller wait for\n          // it for maxScalingDuration time before doing anything else\n          if (ip != null && !\"null\".equals(ip)) {\n            instanceIps.add(ip);\n          } else {\n            // log and skip it\n            log.warn(\"Call returned null IP for %s, skipping\", instance.getName());\n          }\n        }\n        request.setPageToken(response.getNextPageToken());\n      } while (response.getNextPageToken() != null);\n\n      return instanceIps;\n    }\n    catch (Exception e) {\n      log.error(e, \"Unable to convert IDs to IPs.\");\n    }\n\n    return new ArrayList<>();\n  }\n\n  @Override\n  public String toString()\n  {\n    return \"gceAutoScaler={\" +","sourceCodeStart":461,"sourceCodeEnd":497,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-contrib/gce-extensions/src/main/java/org/apache/druid/indexing/overlord/autoscaling/gce/GceAutoScaler.java#L461-L497","documentation":"GceAutoScaler resolves GCE instance names to IPs when scaling out. When the GCE API lookup returns null or the literal string \"null\" for an instance, the scaler logs this warning and skips the instance instead of adding a bogus 'null' host that callers would wait on for maxScalingDuration.","triggerScenarios":"Calling idToIpLookup (via ips1/ips3) for a GCE instance that has no external/internal IP yet: instance still provisioning, instance terminated while listing, or the network interface access config missing (no external IP assigned).","commonSituations":"Autoscaling during rapid scale-up where new workers have not finished provisioning; GCE instances launched without external IPs on networks relying on internal-only addressing; transient GCE API inconsistencies during concurrent termination.","solutions":["Wait and retry: the instance may still be provisioning; verify the instance reaches RUNNING state with an assigned IP in the GCE console.","If instances are intentionally internal-only, configure the autoScaler to read the internal network interface IP instead of the external access config.","Check that the instance's network interface has an access config (external IP) or that the lookup code targets the correct NIC.","Investigate why the GCE API returned the literal \"null\" string — often an outdated metadata/API response; update the GCE client library version."],"exampleFix":"// before\nif (ip != null && !\"null\".equals(ip)) {\n  instanceIps.add(ip);\n}\n// after\nString ip = getInternalIp(instance); // prefer NIC networkInterfaces[0].networkIP\nif (ip != null && !\"null\".equals(ip) && !ip.isEmpty()) {\n  instanceIps.add(ip);\n} else {\n  log.warnEvents(\"Instance %s has no usable IP yet; will retry next poll\", instance.getName());\n}","handlingStrategy":"retry","validationCode":"Instance instance = compute.instances().get(project, zone, name).execute();\nboolean hasIp = instance.getNetworkInterfaces().stream()\n    .anyMatch(nic -> nic.getAccessConfigs() != null && nic.getAccessConfigs().stream()\n        .anyMatch(ac -> ac.getNatIP() != null));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Poll for instance readiness (RUNNING + IP assigned) before including it in scaling results.","Assign static/ephemeral external IPs deliberately, or read the internal IP for internal-only networks.","Keep the GCE API client library up to date to avoid literal \"null\" string responses.","Set maxScalingDuration high enough that a skipped instance does not stall scaling decisions."],"tags":["gce","autoscaling","network","ip-lookup"],"backgroundTag":"empty-result-set","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}