hashicorp/nomad · error

file %s not found under path %s

Error message

file %s not found under path %s

What it means

lookupTaskBin resolves a task's binary to a path inside the task directory. When the binary string contains a '/' it cannot fall back to a PATH-style search, so if it was not already found under the task dir this error is thrown. It means the explicitly-pathed binary does not exist inside the task's filesystem root.

Source

Thrown at drivers/shared/executor/executor_linux_cgo.go:1015

	}

	// Check at the root of the task's directory
	taskPath, hostPath, err = getPathInTaskDir(command.TaskDir, command.TaskDir, bin)
	if err == nil {
		return taskPath, hostPath, nil
	}

	// Check in our mounts
	for _, mount := range command.Mounts {
		taskPath, hostPath, err = getPathInMount(mount.HostPath, mount.TaskPath, bin)
		if err == nil {
			return taskPath, hostPath, nil
		}
	}

	// If there's a / in the binary's path, we can't fallback to a PATH search
	if strings.Contains(bin, "/") {
		return "", "", fmt.Errorf("file %s not found under path %s", bin, taskDir)
	}

	// look for a file using a PATH-style lookup inside the directory
	// root. Similar to the stdlib's exec.LookPath except:
	//   - uses a restricted lookup PATH rather than the agent process's PATH env var.
	//   - does not require that the file is already executable (this will be ensured
	//     by the caller)
	//   - does not prevent using relative path as added to exec.LookPath in go1.19
	//     (this gets fixed-up in the caller)

	// This is a fake PATH so that we're not using the agent's PATH
	restrictedPaths := []string{"/usr/local/bin", "/usr/bin", "/bin"}

	for _, dir := range restrictedPaths {
		pathDir := filepath.Join(command.TaskDir, dir)
		taskPath, hostPath, err = getPathInTaskDir(command.TaskDir, pathDir, bin)
		if err == nil {
			return taskPath, hostPath, nil

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Verify the file exists at the given relative path inside the task dir (check allocation dir on the client)
  2. Fix the bin path in the job spec or ensure artifacts/templates produce the file before launch
  3. Use a bare binary name (no '/') so the PATH-style lookup in task dir runs
  4. Check artifact destination and unzipping settings so the binary lands where bin points

Example fix

// before (job)
command = "./bin/missing-app"
// after
artifact { source = "..."; destination = "local/bin" }
command = "local/bin/app"
Defensive patterns

Strategy: validation

Validate before calling

bin := task.Command
if strings.Contains(bin, "/") {
    p := filepath.Join(allocDir, bin)
    if _, err := os.Stat(p); err != nil {
        return fmt.Errorf("binary %s not present in task dir before launch", bin)
    }
}

Try / catch

if err != nil && strings.Contains(err.Error(), "not found under path") {
    return fmt.Errorf("check command path/artifacts: %w", err)
}

Prevention

When it happens

Trigger: Launch is called with a command whose binary includes a '/' (e.g. ./bin/app or /opt/tool) and lookupTaskBin cannot find that file in the task dir or mount paths before hitting this check.

Common situations: Job specifies bin = "./myapp" but the artifact was not downloaded/extracted into the task dir; binary placed under chroot-unfriendly absolute path; driver template or env misconfiguration producing wrong path; case-sensitivity mismatch on the path.

Related errors


AI-assisted analysis of hashicorp/nomad@482b49bf1a (2026-09-04). Data as JSON: /api/errors/725f68c3c135868c. Report an issue: GitHub.