{"record":{"id":"0d1bb10c4e0f04e6","repo":"hashicorp/nomad","slug":"volumes-are-not-enabled-cannot-use-volume-driver","errorCode":null,"errorMessage":"volumes are not enabled; cannot use volume driver %q","messagePattern":"volumes are not enabled; cannot use volume driver %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/docker/driver.go","lineNumber":768,"sourceCode":"\tif err != nil {\n\t\treturn fmt.Errorf(\"the image does not exist: %v\", err)\n\t}\n\t// LCOW If we are running a Linux Container on Windows, we need to mount it correctly, as c:\\ does not exist on unix\n\tif imageConfig.Os == \"linux\" {\n\t\ta := []rune(task.Env[taskenv.AllocDir])\n\t\ttask.Env[taskenv.AllocDir] = strings.ReplaceAll(string(a[2:]), \"\\\\\", \"/\")\n\t\tl := []rune(task.Env[taskenv.TaskLocalDir])\n\t\ttask.Env[taskenv.TaskLocalDir] = strings.ReplaceAll(string(l[2:]), \"\\\\\", \"/\")\n\t\ts := []rune(task.Env[taskenv.SecretsDir])\n\t\ttask.Env[taskenv.SecretsDir] = strings.ReplaceAll(string(s[2:]), \"\\\\\", \"/\")\n\t}\n\treturn nil\n}\n\nfunc (d *Driver) containerBinds(task *drivers.TaskConfig, driverConfig *TaskConfig) ([]string, error) {\n\ttaskLocalBindVolume := driverConfig.VolumeDriver == \"\"\n\tif !d.config.Volumes.Enabled && !taskLocalBindVolume {\n\t\treturn nil, fmt.Errorf(\"volumes are not enabled; cannot use volume driver %q\", driverConfig.VolumeDriver)\n\t}\n\n\tallocDirBind := fmt.Sprintf(\"%s:%s\", task.TaskDir().SharedAllocDir, task.Env[taskenv.AllocDir])\n\ttaskLocalBind := fmt.Sprintf(\"%s:%s\", task.TaskDir().LocalDir, task.Env[taskenv.TaskLocalDir])\n\tsecretDirBind := fmt.Sprintf(\"%s:%s\", task.TaskDir().SecretsDir, task.Env[taskenv.SecretsDir])\n\tselinuxLabel := d.config.Volumes.SelinuxLabel\n\n\tbinds := []string{allocDirBind, taskLocalBind, secretDirBind}\n\n\tlogsROFlag := \"ro\"\n\tif selinuxLabel != \"\" {\n\t\t// Apply SELinux Label to each built-in bind\n\t\tfor i := range binds {\n\t\t\tbinds[i] = fmt.Sprintf(\"%s:%s\", binds[i], selinuxLabel)\n\t\t}\n\t\tlogsROFlag = \"ro,\" + selinuxLabel\n\t}\n\tallocLogsDirBind := fmt.Sprintf(\"%s/logs:%s/logs:%s\", task.TaskDir().SharedAllocDir, task.Env[taskenv.AllocDir], logsROFlag)","sourceCodeStart":750,"sourceCodeEnd":786,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/docker/driver.go#L750-L786","documentation":"containerBinds rejects volume usage when host volumes are globally disabled on the docker driver (client option volumes.enabled = false) but the task specifies a non-empty volume_driver. Bind mounts of the alloc/task/secret dirs are always allowed, but any explicit volume driver implies a host/volume-driver mount that requires volumes to be enabled. This is a client-level security policy guard.","triggerScenarios":"Task sets config.volume_driver (e.g. \"local\", \"cloudstor:azure\", or a named host volume driver) while the Nomad client docker plugin config has volumes.enabled = false. Raised in createContainerConfig before container creation.","commonSituations":"Jobs migrated from clusters with volumes enabled to locked-down clients; setting volume_driver = \"local\" for docker named volumes on a security-hardened client; forgetting to enable volumes in the client's plugin configuration.","solutions":["Enable volumes on the client: set plugin 'docker' config volumes { enabled = true } in the client hcl and restart.","Remove the volume_driver field if only default alloc-dir bind mounts are needed.","Switch to Nomad host volumes / CSI volumes, which have their own ACL-gated access model.","If only bind mounts are intended, omit volume_driver so taskLocalBindVolume is true."],"exampleFix":"// before (client config)\nplugin \"docker\" { config { volumes { enabled = false } } }\n// after\nplugin \"docker\" { config { volumes { enabled = true } } }","handlingStrategy":"validation","validationCode":"// job-side guard before using volume_driver\nif cfg.VolumeDriver != \"\" && !clientVolumesEnabled {\n\treturn fmt.Errorf(\"job requires volume_driver %q but client volumes are disabled\", cfg.VolumeDriver)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep client volume policy and job requirements documented together","Prefer Nomad host volumes/CSI over docker volume_driver","Omit volume_driver when only alloc-dir bind mounts are needed","Run `nomad job validate` against a client with the same policy"],"tags":["docker","volumes","security-policy"],"backgroundTag":"volumes-disabled","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}