hashicorp/nomad · error

volumes are not enabled; cannot mount host path: %q

Error message

volumes are not enabled; cannot mount host path: %q

What it means

When host volume mounts are disabled (d.config.Volumes.Enabled is false), containerBinds still allows relative/task-dir sources but checks with escapingfs.ChildEscapesParentDir that the source stays inside the allocation directory. This error means the requested bind's source escapes the alloc dir while host-path mounting is forbidden — a security guard against host filesystem access.

Source

Thrown at drivers/docker/driver.go:812

			return nil, fmt.Errorf("invalid docker volume %q: %v", userbind, err)
		}

		// Paths inside task dir are always allowed when using the default driver,
		// Relative paths are always allowed as they mount within a container
		// When a VolumeDriver is set, we assume we receive a binding in the format
		// volume-name:container-dest
		// Otherwise, we assume we receive a relative path binding in the format
		// relative/to/task:/also/in/container
		if taskLocalBindVolume {
			src = expandPath(task.TaskDir().Dir, src)
		} else {
			// Resolve dotted path segments
			src = filepath.Clean(src)
		}

		if !d.config.Volumes.Enabled {
			if err := escapingfs.ChildEscapesParentDir(task.AllocDir, src); err != nil {
				return nil, fmt.Errorf("volumes are not enabled; cannot mount host path: %q", userbind)
			}
		}

		bind := src + ":" + dst
		opts := mode
		if opts != "" {
			if selinuxLabel != "" {
				opts += "," + selinuxLabel
			}
		} else {
			opts = selinuxLabel
		}
		if opts != "" {
			bind += ":" + opts
		}
		binds = append(binds, bind)
	}

View on GitHub (pinned to 482b49bf1a)

Solutions

  1. Remove the host-path bind from config.volumes, or restrict it to paths within the alloc dir.
  2. Enable volumes on the client if host-path mounts are genuinely required (with operator approval).
  3. Use Nomad host volumes declared in client config and referenced via the volume stanza, which are ACL-controlled.
  4. Fix relative paths that use '..' to escape the allocation directory.

Example fix

// before
config { volumes = ["/etc/passwd:/tmp/passwd:ro"] }
// after
config { volumes = ["local/data:/data:ro"] }
Defensive patterns

Strategy: validation

Validate before calling

func escapesAllocDir(allocDir, src string) bool {
	clean := filepath.Clean(src)
	return !strings.HasPrefix(clean, filepath.Clean(allocDir)+string(os.PathSeparator)) && !filepath.IsAbs(clean) == false && strings.HasPrefix(clean, "..")
}

Prevention

When it happens

Trigger: config.volumes entry whose cleaned source path resolves outside task.AllocDir (e.g. "/etc", "../../hostpath", or an absolute host path) while the client has volumes.enabled = false. Raised in createContainerConfig.

Common situations: Jobs copied from dev clusters where volumes were enabled; attempts to mount host paths like /var/run/docker.sock without enabling volumes; relative paths with too many '..' segments escaping the alloc dir.

Related errors


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