google/tsunami-security-scanner · error · ParameterException

Language server path

Error message

Language server path %s does not exist

What it means

LanguageServerOptions.validate() checks each configured --plugin-server-filename path and throws a ParameterException (picocli) if the path does not exist on the local filesystem. This ensures Tsunami only starts configured language/plugin servers that actually point to a file.

Solutions

  1. Verify the path exists (ls / Files.exists) and correct the --plugin-server-filename value.
  2. Use absolute paths in the Tsunami config to avoid working-directory confusion.
  3. Build or install the missing plugin server script before launching.

Example fix

// before
--plugin-server-filename=./python_plugins/pyserver.py  # file missing
// after
--plugin-server-filename=/opt/tsunami/plugins/pyserver.py  # verified existing
Defensive patterns

Strategy: validation

Validate before calling

if (!Files.exists(Paths.get(path))) { throw new IllegalStateException("Language server path missing: " + path); }

Type guard

boolean serverPathExists(String p) { return p != null && Files.exists(Paths.get(p)); }

Try / catch

try { options.validate(); } catch (ParameterException e) { log.error("CLI validation failed: {}", e.getMessage()); }

Prevention

When it happens

Trigger: Running the Tsunami CLI with --plugin-server-filename pointing to a nonexistent file path, or a path that was moved/renamed after configuration.

Common situations: Deploying Tsunami with a config copied from another machine, relative paths resolved from the wrong working directory, or plugin server scripts not built/installed yet.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

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

  public List<String> remotePluginServerAddress = ImmutableList.of();

  @Parameter(
      names = {"--remote-plugin-server-ports", "--python-plugin-server-port"},
      description = "The port of the remote plugin server to open connection with.")
  public List<Integer> remotePluginServerPort = ImmutableList.of();

  @Parameter(
      names = "--remote-plugin-server-rpc-deadline-seconds",
      description = "The RPC deadline in seconds for this plugin server.")
  public List<Integer> remotePluginServerRpcDeadlineSeconds = ImmutableList.of();

  @Override
  public void validate() {
    if (!pluginServerFilenames.isEmpty() || !pluginServerPorts.isEmpty()) {
      if (pluginServerFilenames != null && !pluginServerFilenames.isEmpty()) {
        for (String pluginServerFilename : pluginServerFilenames) {
          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),

View on GitHub (pinned to 363ba87b35)