openzipkin/zipkin · error · IllegalArgumentException

%s is an invalid IPv6 literal

Error message

%s is an invalid IPv6 literal

What it means

Thrown by HostAndPort.fromString when the input contains multiple colons and is not bracketed, and the whole string fails IPv6 validation (it reuses Endpoint's IPv6 validator). An unbracketed multi-colon string can only be legal bare IPv6; anything else (e.g. 'host:1:2') is invalid.

Source

Thrown at zipkin-storage/cassandra/src/main/java/zipkin2/storage/cassandra/internal/HostAndPort.java:70

  public static HostAndPort fromString(String hostPort, int defaultPort) {
    if (hostPort == null) throw new NullPointerException("hostPort == null");

    String host = hostPort;
    int endHostIndex = hostPort.length();
    if (hostPort.startsWith("[")) { // Bracketed IPv6
      endHostIndex = hostPort.lastIndexOf(']') + 1;
      host = hostPort.substring(1, endHostIndex == 0 ? 1 : endHostIndex - 1);
      if (!Endpoint.newBuilder().parseIp(host)) { // reuse our IPv6 validator
        throw new IllegalArgumentException(hostPort + " contains an invalid IPv6 literal");
      }
    } else {
      int colonIndex = hostPort.indexOf(':'), nextColonIndex = hostPort.lastIndexOf(':');
      if (colonIndex >= 0) {
        if (colonIndex == nextColonIndex) { // only 1 colon
          host = hostPort.substring(0, colonIndex);
          endHostIndex = colonIndex;
        } else if (!Endpoint.newBuilder().parseIp(hostPort)) { // reuse our IPv6 validator
          throw new IllegalArgumentException(hostPort + " is an invalid IPv6 literal");
        }
      }
    }
    if (host.isEmpty()) throw new IllegalArgumentException(hostPort + " has an empty host");
    if (endHostIndex + 1 < hostPort.length() && hostPort.charAt(endHostIndex) == ':') {
      return new HostAndPort(host, validatePort(hostPort.substring(endHostIndex + 1), hostPort));
    }
    return new HostAndPort(host, defaultPort);
  }

  static int validatePort(String portString, String hostPort) {
    for (int i = 0, length = portString.length(); i < length; i++) {
      char c = portString.charAt(i);
      if (c >= '0' && c <= '9') continue; // isDigit
      throw new IllegalArgumentException(hostPort + " has an invalid port");
    }
    int result = Integer.parseInt(portString);
    if (result == 0 || result > 0xffff) {

View on GitHub (pinned to 878ce2a1fa)

Solutions

  1. Bracket IPv6 with a port: '[2001:db8::1]:9042'.
  2. For bare IPv6 without port, pass '2001:db8::1' and let defaultPort apply.
  3. Lint contact-point strings at config load for the bracket rule.

Example fix

# before
CASSANDRA_CONTACT_POINTS=2001:db8::1:9042

# after
CASSANDRA_CONTACT_POINTS=[2001:db8::1]:9042
Defensive patterns

Strategy: validation

Validate before calling

static boolean isBareIpv6(String s) { return s != null && s.indexOf(':') != s.lastIndexOf(':') && Endpoint.newBuilder().parseIp(s); }
// When a port is needed with IPv6, require brackets
if (hostPort.indexOf(':') != hostPort.lastIndexOf(':') && !hostPort.startsWith("[")) throw new IllegalArgumentException("Bracket IPv6 with port: [addr]:port");

Type guard

static boolean isIpv6WithOptionalPort(String s) { return s != null && (isBareIpv6(s) || isValidBracketedIpv6(s)); }

Try / catch

catch (IllegalArgumentException e) { if (e.getMessage().endsWith("is an invalid IPv6 literal")) suggestBracketedForm(); else throw e; }

Prevention

When it happens

Trigger: Passing '2001:db8::1:9042' where the embedded ':9042' makes the full string an invalid IPv6 address; passing 'a:b:c' style strings.

Common situations: Forgetting to bracket an IPv6 address that carries a port; config values joined with extra colons.

Related errors


AI-assisted analysis of openzipkin/zipkin@878ce2a1fa (2026-08-14). Data as JSON: /api/errors/de0e6fad9d8c165c. Report an issue: GitHub.