google/tsunami-security-scanner · error · ParameterException

Port number must be an integer. Got

Error message

Port number must be an integer. Got %s instead.

What it means

LanguageServerOptions.validate() parses --plugin-server-port values with Integer.parseInt. A non-numeric value raises NumberFormatException, which is caught and rethrown as a ParameterException telling the user the port must be an integer.

Solutions

  1. Provide plain decimal integer ports, one per flag occurrence (e.g. 8080 8081).
  2. Trim whitespace and split any comma-separated lists into separate flag values.
  3. Validate port strings with a regex ^[0-9]+$ before invoking Tsunami.

Example fix

// before
--plugin-server-port=8080,8081
// after
--plugin-server-port=8080 --plugin-server-port=8081
Defensive patterns

Strategy: validation

Validate before calling

if (portStr.trim().matches("^[0-9]+$")) { /* safe to pass */ }

Type guard

boolean isDecimalInteger(String s) { return s != null && s.trim().matches("\\d+"); }

Try / catch

try { options.validate(); } catch (ParameterException e) { log.error("Non-integer port: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Passing --plugin-server-port values like "8080a", "80 80", "", or "0x1F90" — anything Integer.parseInt cannot parse as a base-10 integer.

Common situations: Whitespace or stray characters in config files, hex port notation pasted from docs, or comma-separated port lists passed as a single value.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


AI-assisted analysis of google/tsunami-security-scanner@363ba87b35 (2026-09-13). Data as JSON: /api/errors/d40bc911f4db9964. Report an issue: GitHub.

Appendix: source

Thrown at main/src/main/java/com/google/tsunami/main/cli/LanguageServerOptions.java:88

          if (!Files.exists(Paths.get(pluginServerFilename))) {
            throw new ParameterException(
                String.format("Language server path %s does not exist", pluginServerFilename));
          }
        }
      }

      if (pluginServerPorts != null && !pluginServerPorts.isEmpty()) {
        for (String pluginServerPort : pluginServerPorts) {
          try {
            int port = Integer.parseInt(pluginServerPort);
            if (!(port <= NetworkEndpointUtils.MAX_PORT_NUMBER && port > 0)) {
              throw new ParameterException(
                  String.format(
                      "Port out of range. Expected [0, %s], actual %s.",
                      NetworkEndpointUtils.MAX_PORT_NUMBER, pluginServerPort));
            }
          } catch (NumberFormatException e) {
            throw new ParameterException(
                String.format("Port number must be an integer. Got %s instead.", pluginServerPort),
                e);
          }
        }
      }

      var pathCounts = pluginServerFilenames == null ? 0 : pluginServerFilenames.size();
      var portCounts = pluginServerPorts == null ? 0 : pluginServerPorts.size();
      if (pathCounts != portCounts) {
        throw new ParameterException(
            String.format(
                "Number of plugin server paths must be equal to number of plugin server ports."
                    + " Paths: %s. Ports: %s.",
                pathCounts, portCounts));
      }

      if (!pluginServerRpcDeadlineSeconds.isEmpty()) {
        if (pluginServerRpcDeadlineSeconds.size() != pathCounts) {

View on GitHub (pinned to 363ba87b35)