elastic/elasticsearch · error · UserException

USAGE

USAGE

Error message

too many arguments, expected one service id

What it means

Thrown by ProcrunCommand.getServiceId when more than one non-option argument is passed on the command line. The Windows service commands accept at most one positional argument, interpreted as the service id; anything beyond that is ambiguous and rejected with exit code USAGE. The check fires before the service id is resolved, so it does not depend on whether SERVICE_ID env var is set.

Source

Thrown at distribution/tools/windows-service-cli/src/main/java/org/elasticsearch/windows/service/ProcrunCommand.java:99

        Process process = startProcess(processBuilder);
        int ret = process.waitFor();
        if (ret != ExitCodes.OK) {
            throw new UserException(ret, getFailureMessage(serviceId));
        } else {
            terminal.println(getSuccessMessage(serviceId));
        }
    }

    /** Quotes the given String. */
    static String quote(String s) {
        return '"' + s + '"';
    }

    /** Determines the service id for the Elasticsearch service that should be used */
    private static String getServiceId(OptionSet options, Map<String, String> env) throws UserException {
        List<?> args = options.nonOptionArguments();
        if (args.size() > 1) {
            throw new UserException(ExitCodes.USAGE, "too many arguments, expected one service id");
        }
        final String serviceId;
        if (args.size() > 0) {
            serviceId = args.get(0).toString();
        } else {
            serviceId = env.getOrDefault("SERVICE_ID", "elasticsearch-service-x64");
        }
        return serviceId;
    }

    /** Determines the logging arguments that should be passed to the procrun command */
    private static String getLogArgs(String serviceId, Path esHome, Map<String, String> env) {
        String logArgs = env.get("LOG_OPTS");
        if (logArgs != null && logArgs.isBlank() == false) {
            return logArgs;
        }
        String logsDir = env.get("SERVICE_LOG_DIR");
        if (logsDir == null || logsDir.isBlank()) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Pass at most one positional argument (the service id), or none to use the SERVICE_ID env var / default.
  2. Quote any value containing spaces: `elasticsearch-service.bat install "my service"`.
  3. Run `elasticsearch-service.bat help` to confirm the expected argument shape.

Example fix

REM before
bin\elasticsearch-service.bat install es-9 es-prod
REM after
set SERVICE_ID=es-9
bin\elasticsearch-service.bat install
Defensive patterns

Strategy: validation

Validate before calling

List<String> positional = options.nonOptionArguments().stream().map(String::valueOf).toList();
if (positional.size() > 1) {
    throw new IllegalArgumentException("Expected at most one service id; got " + positional);
}

Type guard

static boolean atMostOnePositional(List<?> args) {
    return args != null && args.size() <= 1;
}

Try / catch

try {
    String sid = ProcrunCommand.getServiceId(options, env);
} catch (UserException e) {
    if (e.exitCode == ExitCodes.USAGE && e.getMessage().contains("too many arguments")) {
        // re-print help and exit
    } else throw e;
}

Prevention

When it happens

Trigger: Running `elasticsearch-service.bat install foo bar` (two positional args). Passing extra flags without their leading dash so they are parsed as positional. Copy-paste errors adding a stray token.

Common situations: Operators assume the command takes a service name plus an action. Misuse of quoting that splits a single value into two tokens.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/d9d3c38fcd76b98a. Report an issue: GitHub.