nathanmarz/storm · critical · RuntimeException

Could not get canonical path for

Error message

Could not get canonical path for ${_pidDir}

What it means

WorkerTopologyContext's constructor resolves the worker's pid directory to its canonical filesystem path. If File.getCanonicalPath() throws an IOException (e.g. the pidDir path cannot be resolved on disk), it wraps it in a RuntimeException with this message. This is fatal to worker startup because the pid dir is needed for process bookkeeping.

Solutions

  1. Verify the pid directory path exists and is accessible: ls -ld <pidDir> and check permissions for the worker user
  2. Check that storm.local.dir / supervisor local dirs are on a mounted, writable filesystem and the volume is not full
  3. Restart the supervisor/worker so a fresh pid dir is created
  4. Inspect the wrapped IOException cause in the stack trace for the underlying OS-level reason
  5. Enable worker logging to see which path failed and fix stale symlinks

Example fix

// before: passing a possibly-nonexistent dir
new WorkerTopologyContext(topology, config, tasks, taskToComponent, componentToSortedTasks, null, pidDir, workerPort, workerTasks);
// after: ensure dir exists before constructing
Files.createDirectories(new File(pidDir).toPath());
new WorkerTopologyContext(topology, config, tasks, taskToComponent, componentToSortedTasks, null, pidDir, workerPort, workerTasks);
Defensive patterns

Strategy: validation

Validate before calling

File dir = new File(pidDir);
if (!dir.exists() && !dir.mkdirs())
    throw new IllegalStateException("pidDir not creatable: " + pidDir);
try { dir.getCanonicalPath(); } catch (IOException e) { throw new IllegalStateException("pidDir not resolvable: " + pidDir, e); }

Prevention

When it happens

Trigger: Supervisor/worker passes a pidDir path that does not exist or lies on an unmounted/deleted volume, or filesystem-level I/O errors (permissions on parent dirs, broken symlinks) prevent canonicalization when a worker's topology context is constructed.

Common situations: Disk full or the supervisor's local dir (e.g. storm.local.dir) cleaned up underneath a running worker; NFS mounts dropped; pid dir deleted by log-cleanup cron or container restart; mismatched permissions after running as a different user.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of nathanmarz/storm@cdb116e942 (2026-09-12). Data as JSON: /api/errors/78d61eeaa4d8c3ce. Report an issue: GitHub.

Appendix: source

Thrown at storm-core/src/jvm/backtype/storm/task/WorkerTopologyContext.java:63

            String codeDir,
            String pidDir,
            Integer workerPort,
            List<Integer> workerTasks,
            Map<String, Object> defaultResources,
            Map<String, Object> userResources
            ) {
        super(topology, stormConf, taskToComponent, componentToSortedTasks, componentToStreamToFields, stormId);
        _codeDir = codeDir;
        _defaultResources = defaultResources;
        _userResources = userResources;
        try {
            if(pidDir!=null) {
                _pidDir = new File(pidDir).getCanonicalPath();
            } else {
                _pidDir = null;
            }
        } catch (IOException e) {
            throw new RuntimeException("Could not get canonical path for " + _pidDir, e);
        }
        _workerPort = workerPort;
        _workerTasks = workerTasks;
    }

    /**
     * Gets all the task ids that are running in this worker process
     * (including the task for this task).
     */
    public List<Integer> getThisWorkerTasks() {
        return _workerTasks;
    }
    
    public Integer getThisWorkerPort() {
        return _workerPort;
    }

    /**

View on GitHub (pinned to cdb116e942)