elastic/elasticsearch · error · UserException

ret

ret

Error message

Failed ${action} '${serviceId}' service

What it means

Thrown by ProcrunCommand.execute when the underlying procrun executable returns a non-zero exit code. The UserException carries that exit code (`ret`) so the CLI exits with the same value procrun used. The message is templated by getFailureMessage(serviceId) and typically says something like `Failed installing service 'elasticsearch-service-x64'`. This is a passthrough of procrun's own failure, not a Java-level error.

Source

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

        }
        String serviceId = getServiceId(options, processInfo.envVars());
        preExecute(terminal, processInfo, serviceId);

        List<String> procrunCmd = new ArrayList<>();
        procrunCmd.add(quote(procrun.toString()));
        procrunCmd.add("//%s/%s".formatted(cmd, serviceId));
        if (includeLogArgs()) {
            procrunCmd.add(getLogArgs(serviceId, processInfo.workingDir(), processInfo.envVars()));
        }
        procrunCmd.add(getAdditionalArgs(serviceId, processInfo));

        ProcessBuilder processBuilder = new ProcessBuilder("cmd.exe", "/C", String.join(" ", procrunCmd).trim());
        logger.debug((Supplier<?>) () -> "Running procrun: " + String.join(" ", processBuilder.command()));
        processBuilder.inheritIO();
        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) {

View on GitHub (pinned to db6a809a66)

Solutions

  1. Run the command from an Administrator shell.
  2. For install failures, check if the service already exists: `sc query <serviceId>` and remove it first with the `remove` subcommand.
  3. Read the procrun log files (default in logs/) for the underlying Windows error code.
  4. Confirm the service id matches across install/manage/remove invocations.

Example fix

REM before (service already registered)
bin\elasticsearch-service.bat install
REM after
bin\elasticsearch-service.bat remove
bin\elasticsearch-service.bat install
Defensive patterns

Strategy: try-catch

Validate before calling

// Before invoking, check whether the service is in the expected state for the action:
// e.g. for 'install', assert the service is absent:
Process p = new ProcessBuilder("sc", "query", serviceId).redirectErrorStream(true).start();
if (p.waitFor() == 0) {
    throw new IllegalStateException("Service " + serviceId + " already exists; remove it first.");
}

Type guard

static boolean serviceIsRegistered(String serviceId) throws IOException, InterruptedException {
    Process p = new ProcessBuilder("sc", "query", serviceId).start();
    return p.waitFor() == 0;
}

Try / catch

try {
    procrunCmd.execute(...);
} catch (UserException e) {
    // e.exitCode mirrors procrun's exit code; surface the procrun logs/
    log.error("procrun {} failed for service {} (exit {}); see logs/", cmd, serviceId, e.exitCode, e);
    throw e;
}

Prevention

When it happens

Trigger: Installing a service that already exists. Removing or stopping a service that is not installed/running. Running without the Administrator privileges procrun requires for service operations. Supplying a service id that collides with an existing service.

Common situations: Re-running `install` after a previous failed uninstall left the service registered. Non-admin shell. Service name conflicts with another product.

Related errors


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