{"record":{"id":"e23702dc858327c9","repo":"hashicorp/nomad","slug":"volumes-are-not-enabled-cannot-mount-volume-q","errorCode":null,"errorMessage":"volumes are not enabled; cannot mount volume: %q","messagePattern":"volumes are not enabled; cannot mount volume: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"drivers/docker/driver.go","lineNumber":1628,"sourceCode":"\thm, err := m.toDockerHostMount()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tswitch hm.Type {\n\tcase \"bind\":\n\t\thm.Source = expandPath(task.TaskDir().Dir, hm.Source)\n\n\t\tif !d.config.Volumes.Enabled {\n\t\t\tif err := escapingfs.ChildEscapesParentDir(task.AllocDir, hm.Source); err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"volumes are not enabled; cannot mount host path: %q\", hm.Source)\n\t\t\t}\n\t\t}\n\tcase \"tmpfs\":\n\t\t// no source, so no sandbox check required\n\tdefault: // \"volume\", but also any new thing that comes along\n\t\tif !d.config.Volumes.Enabled {\n\t\t\treturn nil, fmt.Errorf(\n\t\t\t\t\"volumes are not enabled; cannot mount volume: %q\", hm.Source)\n\t\t}\n\t}\n\n\treturn &hm, nil\n}\n\n// detectIP of Docker container. Returns the first IP found as well as true if\n// the IP should be advertised (bridge network IPs return false). Returns an\n// empty string and false if no IP could be found.\nfunc (d *Driver) detectIP(c mclient.ContainerInspectResult, driverConfig *TaskConfig) (string, bool) {\n\tif c.Container.NetworkSettings == nil {\n\t\t// This should only happen if there's been a coding error (such\n\t\t// as not calling InspectContainer after CreateContainer). Code\n\t\t// defensively in case the Docker API changes subtly.\n\t\td.logger.Error(\"no network settings for container\", \"container_id\", c.Container.ID)\n\t\treturn \"\", false\n\t}","sourceCodeStart":1610,"sourceCodeEnd":1646,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/drivers/docker/driver.go#L1610-L1646","documentation":"When docker volumes are disabled on the client (volumes.enabled=false), any mount whose type is not \"bind\" or \"tmpfs\" — typically type=\"volume\" — is rejected outright in toDockerMount. Named Docker volumes are only permitted when the client operator has enabled them.","triggerScenarios":"A task config declares a mount with type=\"volume\" (or a novel type) while the client's docker plugin config has volumes.enabled=false.","commonSituations":"Jobs referencing named docker volumes on clients where the operator disabled them for security; copy-pasted job files from environments with volumes enabled.","solutions":["Set volumes.enabled=true in the client's docker plugin config if named volumes are acceptable.","Switch the mount to type=\"tmpfs\" (in-memory) or a relative bind inside the alloc dir.","Use a Nomad host_volume or CSI volume with explicit job-level allow-listing instead of a raw docker named volume."],"exampleFix":"// before\nmounts = [{ type = \"volume\", source = \"mydata\", target = \"/data\" }]\n// after\n# client.hcl: plugin \"docker\" { config { volumes { enabled = true } } }\n# or use: mounts = [{ type = \"tmpfs\", target = \"/data\" }]","handlingStrategy":"validation","validationCode":"// reject volume-type mounts when the target client has docker volumes disabled\nif mountType == \"volume\" && !clientDockerVolumesEnabled {\n    return fmt.Errorf(\"volume mount %q needs volumes.enabled=true on client\", source)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Confirm client docker plugin volumes.enabled before using type=\"volume\" mounts","Prefer Nomad host_volume/CSI volumes for portable, allow-listed storage","Use tmpfs mounts for ephemeral scratch space instead of named volumes"],"tags":["docker","nomad","volumes","security-sandbox"],"backgroundTag":"host-volume-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"}