apache/cassandra · error · IllegalArgumentException

Invalid directory

Error message

Invalid directory {directory}

What it means

bulkLoadInternal(directory) is the implementation behind `nodetool refresh`/bulk load APIs. It validates that the given path exists and is a directory; otherwise it throws IllegalArgumentException. The path is resolved on the Cassandra server host, not the client machine.

Solutions

  1. Verify the path on the node: it must exist and be a directory containing SSTable files (with -db, -TOC, etc. components)
  2. Run nodetool refresh on the correct host where the SSTables were placed (scp first if remote)
  3. Place SSTables under the table's upload directory or any directory the cassandra process can read
  4. Check container volume mappings if running Cassandra in Docker - the path must be visible inside the container

Example fix

// before: client-local path passed to remote node
nodetool refresh ks tbl /local/tmp/sstables
// after: copy files to the server, then refresh
scp -r /local/tmp/sstables node:/var/lib/cassandra/data/ks/tbl-upload-ks-tbl-ks-tbl/
ssh node 'nodetool refresh ks tbl'
Defensive patterns

Strategy: validation

Validate before calling

File dir = new File(directory);
if (!dir.exists() || !dir.isDirectory())
    throw new IllegalArgumentException("not a server-side directory: " + directory);

Type guard

boolean isBulkLoadableDir(String path) {
    File d = new File(path);
    return d.exists() && d.isDirectory();
}

Try / catch

try { ss.bulkLoad(directory); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Invalid directory")) { log.error("path missing on server host: {}", directory); } throw e; }

Prevention

When it happens

Trigger: Calling `nodetool refresh <keyspace> <cf>` or StorageService.bulkLoad(path) with a path that doesn't exist on the server, or that is a file rather than a directory of SSTables.

Common situations: Copying SSTables to the wrong host or a path the cassandra user can't see; passing a local path from a remote nodetool client; staging files under a truncated/renamed directory; docker/container path mismatch.

Related errors


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

Appendix: source

Thrown at src/java/org/apache/cassandra/service/StorageService.java:4546

            bulkLoadInternal(directory).get();
        }
        catch (Exception e)
        {
            throw new RuntimeException(e);
        }
    }

    public String bulkLoadAsync(String directory)
    {
        return bulkLoadInternal(directory).planId.toString();
    }

    private StreamResultFuture bulkLoadInternal(String directory)
    {
        File dir = new File(directory);

        if (!dir.exists() || !dir.isDirectory())
            throw new IllegalArgumentException("Invalid directory " + directory);

        SSTableLoader.Client client = new SSTableLoader.Client()
        {
            private String keyspace;

            public void init(String keyspace)
            {
                this.keyspace = keyspace;
                try
                {
                    for (Map.Entry<Range<Token>, EndpointsForRange> entry : getRangeToAddressMap(keyspace).entrySet())
                    {
                        Range<Token> range = entry.getKey();
                        EndpointsForRange replicas = entry.getValue();
                        Replicas.temporaryAssertFull(replicas);
                        for (InetAddressAndPort endpoint : replicas.endpoints())
                            addRangeForEndpoint(range, endpoint);
                    }

View on GitHub (pinned to 88fd0f6a0e)