{"record":{"id":"4e84b4577c898821","repo":"GoogleContainerTools/jib","slug":"invalid-port-configuration-port-make-sure-th","errorCode":null,"errorMessage":"Invalid port configuration: '<port>'. Make sure the port is a single number or a range of two numbers separated with a '-', with or without protocol specified (e.g. '<portNum>/tcp' or '<portNum>/udp').","messagePattern":"Invalid port configuration: '<port>'\\. Make sure the port is a single number or a range of two numbers separated with a '-', with or without protocol specified \\(e\\.g\\. '<portNum>/tcp' or '<portNum>/udp'\\)\\.","errorType":"validation","errorClass":"NumberFormatException","httpStatus":null,"severity":"error","filePath":"jib-core/src/main/java/com/google/cloud/tools/jib/api/Ports.java","lineNumber":56,"sourceCode":"   * Converts/validates a list of strings representing port ranges to an expanded list of {@link\n   * Port}s.\n   *\n   * <p>For example: [\"1000\", \"2000-2002\"] will expand to a list of {@link Port}s with the port\n   * numbers [1000, 2000, 2001, 2002]\n   *\n   * @param ports the list of port numbers/ranges, with an optional protocol separated by a '/'\n   *     (defaults to TCP if missing).\n   * @return the ports as a list of {@link Port}\n   * @throws NumberFormatException if any of the ports are in an invalid format or out of range\n   */\n  public static Set<Port> parse(List<String> ports) throws NumberFormatException {\n    Set<Port> result = new HashSet<>();\n\n    for (String port : ports) {\n      Matcher matcher = portPattern.matcher(port);\n\n      if (!matcher.matches()) {\n        throw new NumberFormatException(\n            \"Invalid port configuration: '\"\n                + port\n                + \"'. Make sure the port is a single number or a range of two numbers separated \"\n                + \"with a '-', with or without protocol specified (e.g. '<portNum>/tcp' or \"\n                + \"'<portNum>/udp').\");\n      }\n\n      // Parse protocol\n      int min = Integer.parseInt(matcher.group(1));\n      int max = min;\n      if (!Strings.isNullOrEmpty(matcher.group(2))) {\n        max = Integer.parseInt(matcher.group(2));\n      }\n      String protocol = matcher.group(3);\n\n      // Error if configured as 'max-min' instead of 'min-max'\n      if (min > max) {\n        throw new NumberFormatException(","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/GoogleContainerTools/jib/blob/fb949e2676afbbd7dd7a1ef61e20251931325654/jib-core/src/main/java/com/google/cloud/tools/jib/api/Ports.java#L38-L74","documentation":"Ports.parse validates each port specification string against a regex allowing a single number or a range 'min-max', optionally followed by /tcp or /udp. If a string does not match this pattern, it throws NumberFormatException with a message explaining the accepted formats. The exception happens before any port is added to the result set.","triggerScenarios":"Calling Ports.parse(...) with malformed strings such as \"80x443\", \"http\", \"80-90-100\", \"  80\", \"80/https\", or \"8080/\" (trailing slash, whitespace, letters, wrong separators).","commonSituations":"Docker-compose-style port mappings like '8080:80' pasted into Jib's exposedPorts config; environment-variable-driven port lists containing empty strings; YAML/JSON config with protocol typos like '/TCP' uppercase.","solutions":["Use valid formats: '80', '80-90', '8080/tcp', '53/udp', '1000-2000/udp'.","Fix Docker-style mappings by splitting on ':' and taking the container port ('8080:80' -> '80').","Trim strings and remove empty entries before passing the list to parse.","Lowercase the protocol suffix (/tcp, /udp) to match the pattern.","Add pre-validation with a regex like ^\\d+(-\\d+)?(/(tcp|udp))?$ in your config loading code."],"exampleFix":"// before\nList<String> ports = env(\"PORTS\").split(\",\"); // may contain \"\" or \"8080:80\"\nPortList.addAll(Ports.parse(ports));\n// after\nList<String> ports = Arrays.stream(env(\"PORTS\").split(\",\"))\n    .map(String::trim).filter(s -> !s.isEmpty())\n    .map(s -> s.contains(\":\") ? s.substring(s.indexOf(':') + 1) : s)\n    .collect(Collectors.toList());\nPortList.addAll(Ports.parse(ports));","handlingStrategy":"validation","validationCode":"Pattern OK = Pattern.compile(\"^\\\\d+(-\\\\d+)?(/(tcp|udp))?$\");\nfor (String p : ports) { if (!OK.matcher(p.trim()).matches()) throw new IllegalArgumentException(\"bad port: \" + p); }","typeGuard":"null","tryCatchPattern":"try { Set<Port> parsed = Ports.parse(ports); } catch (NumberFormatException e) { log.error(\"Bad port spec: {}\", e.getMessage()); throw new ConfigException(e); }","preventionTips":["Normalize/trim inputs and drop empties before parse","Convert Docker 'host:container' mappings to container ports only","Document accepted formats wherever port config is exposed","Add unit tests for Ports.parse edge cases"],"tags":["validation","ports","config"],"backgroundTag":"invalid-argument-format","analyzedSha":"fb949e2676afbbd7dd7a1ef61e20251931325654","analyzedAt":"2026-09-06T14:04:09.491Z","contentChangedAt":"2026-09-06T14:04:09.491Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}