apache/cassandra · error · IllegalArgumentException

The results path ( ) should be an existing directory

Error message

The results path (${basePath}) should be an existing directory

What it means

Replay.run validates that the --results path, when provided, already exists and is a directory; it does not create it. If the path is missing or a regular file, it prints the message to stderr and throws IllegalArgumentException. Per-target subdirectories are then created inside it for comparison results.

Solutions

  1. Create the directory beforehand: mkdir -p /path/to/results
  2. Point --results at an existing directory, not a file
  3. Fix typos in the --results argument

Example fix

// before
fqltool replay ... --results /tmp/nonexistent
// after
mkdir -p /tmp/results
fqltool replay ... --results /tmp/results
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
function validateResultsPath(p) {
  const st = fs.statSync(p);
  if (!st.isDirectory()) throw new Error('--results must be an existing directory: ' + p);
}

Type guard

const isExistingDirectory = p => { try { return require('fs').statSync(p).isDirectory(); } catch { return false; } };

Try / catch

try { runReplay(args); } catch (IllegalArgumentException e) { if (e.getMessage().contains("should be an existing directory")) { exitWith("create the directory first: mkdir -p " + args.results); } else throw e; }

Prevention

When it happens

Trigger: Running fqltool replay with --results pointing to a non-existent path or an existing file rather than a directory.

Common situations: Typos in the results path; assuming the tool creates the directory; pointing at a results file from a previous run.

Related errors


AI-assisted analysis of apache/cassandra@88fd0f6a0e (2026-09-10). Data as JSON: /api/errors/ec9361ef1298fa56. Report an issue: GitHub.

Appendix: source

Thrown at tools/fqltool/src/org/apache/cassandra/fqltool/commands/Replay.java:85

    @Option(paramLabel = "store_queries", names = { "--store-queries" }, description = "Path to store the queries executed. Stores queries in the same order as the result sets are in the result files. Requires --results")
    private String queryStorePath;

    @Option(paramLabel = "replay_ddl_statements", names = { "--replay-ddl-statements" }, description = "If specified, replays DDL statements as well, they are excluded from replaying by default.")
    private boolean replayDDLStatements;

    @Override
    public void run()
    {
        try
        {
            List<File> resultPaths = null;
            if (resultPath != null)
            {
                File basePath = new File(resultPath);
                if (!basePath.exists() || !basePath.isDirectory())
                {
                    System.err.println("The results path (" + basePath + ") should be an existing directory");
                    throw new IllegalArgumentException("The results path (" + basePath + ") should be an existing directory");
                }
                resultPaths = targetHosts.stream().map(target -> new File(basePath, target)).collect(Collectors.toList());
                resultPaths.forEach(File::mkdir);
            }
            if (targetHosts.size() < 1)
            {
                throw new IllegalArgumentException("You need to state at least one --target host to replay the query against");
            }
            replay(keyspace, arguments, targetHosts, resultPaths, queryStorePath, replayDDLStatements);
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }

    public static void replay(String keyspace, List<String> arguments, List<String> targetHosts, List<File> resultPaths, String queryStorePath, boolean replayDDLStatements)
    {

View on GitHub (pinned to 88fd0f6a0e)