{"record":{"id":"370b732ffd094abe","repo":"hashicorp/nomad","slug":"error-creating-directory-w","errorCode":null,"errorMessage":"error creating directory: %w","messagePattern":"error creating directory: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/hostvolumemanager/host_volume_plugin.go","lineNumber":136,"sourceCode":"\tif _, err := os.Stat(path); err == nil {\n\t\t// already exists\n\t\treturn resp, nil\n\t} else if !os.IsNotExist(err) {\n\t\t// doesn't exist, but some other path error\n\t\tlog.Error(\"error with path\", \"error\", err)\n\t\treturn nil, err\n\t}\n\n\tparams, err := decodeMkdirParams(req.Parameters)\n\tif err != nil {\n\t\tlog.Error(\"error with parameters\", \"error\", err)\n\t\treturn nil, err\n\t}\n\n\terr = os.MkdirAll(path, params.Mode)\n\tif err != nil {\n\t\tlog.Error(\"error creating directory\", \"error\", err)\n\t\treturn nil, fmt.Errorf(\"error creating directory: %w\", err)\n\t}\n\n\t// os.MkdirAll perms are applied after umask, so the new directory may not\n\t// have the exact permissions requested.\n\terr = os.Chmod(path, params.Mode)\n\tif err != nil {\n\t\tlog.Error(\"error setting directory permission mode\", \"error\", err)\n\t\treturn nil, fmt.Errorf(\"error setting directory permission mode: %w\", err)\n\t}\n\n\tif runtime.GOOS != \"windows\" {\n\t\t// Chown note: A uid or gid of -1 means to not change that value.\n\t\tif err = os.Chown(path, params.Uid, params.Gid); err != nil {\n\t\t\tlog.Error(\"error changing owner/group\", \"error\", err, \"uid\", params.Uid, \"gid\", params.Gid)\n\n\t\t\t// Failing to change ownership is fatal for this plugin. Since we have\n\t\t\t// already created the directory, we should attempt to clean it.\n\t\t\t// Otherwise, the operator must do this manually.","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/hostvolumemanager/host_volume_plugin.go#L118-L154","documentation":"This error wraps the failure of os.MkdirAll when a host volume plugin's Create operation tries to create the requested directory on the client. It means the directory could not be created at the requested path with the requested mode — the wrapped cause (permission denied, path exists as a file, nonexistent parent, full disk, etc.) is included via %w. Nomad logs the raw error and returns this wrapped error to the caller (the host volume manager), which surfaces it in the volume create RPC result.","triggerScenarios":"Calling the plugin Create operation (HostVolumePlugin.Create, reached via client host volume manager) where os.MkdirAll(path, params.Mode) fails: parent directory missing and cannot be created, permission denied on the target path, a non-directory file already exists at path, path is invalid/too long, or the filesystem is read-only or full.","commonSituations":"Operator submits a host volume create request with a path under a directory the nomad client user cannot write to (e.g. /var/lib/volumes owned by root); a regular file already exists at the requested path; the volume path points to a read-only mount or NFS export without write access; SELinux/AppArmor blocking mkdir.","solutions":["Check the wrapped cause (errors.Unwrap / %v of err) and fix the underlying OS problem — most often chown/chmod the parent directory so the nomad client user can create the path.","Verify no regular file occupies the requested path (ls -l the path; remove or choose a different path).","Confirm the parent directory chain exists and is on a writable filesystem (not read-only mount, not full disk: df, mount).","If SELinux/AppArmor is enforcing, add appropriate policy or choose another path."],"exampleFix":"// before: plugin fails because client user cannot write to parent\nparams := api.HostVolumeCreateParams{ Path: \"/volumes/teamdata\", Mode: 0o755 }\n\n// after: pre-create and own the parent as an operator\n// sudo mkdir -p /volumes && sudo chown nomad:nomad /volumes\nparams := api.HostVolumeCreateParams{ Path: \"/volumes/teamdata\", Mode: 0o755 }","handlingStrategy":"validation","validationCode":"import \"os\"\n\nfunc canCreateDir(path string) error {\n    if fi, err := os.Lstat(path); err == nil && !fi.IsDir() {\n        return fmt.Errorf(\"%s exists and is not a directory\", path)\n    }\n    parent := filepath.Dir(path)\n    if fi, err := os.Stat(parent); err != nil || !fi.IsDir() {\n        return fmt.Errorf(\"parent %s missing or not a directory\", parent)\n    }\n    f, err := os.CreateTemp(parent, \".wtest*\")\n    if err != nil {\n        return fmt.Errorf(\"no write permission in %s: %w\", parent, err)\n    }\n    f.Close(); os.Remove(f.Name())\n    return nil\n}","typeGuard":null,"tryCatchPattern":"var hvErr *hvapi.Error\nif errors.As(err, &hvErr) && strings.Contains(hvErr.Error(), \"error creating directory\") {\n    var pathErr *os.PathError\n    if errors.As(errors.Unwrap(err), &pathErr) && errors.Is(pathErr.Err, fs.ErrPermission) {\n        // escalate to operator: fix ownership/permissions of parent\n    }\n}","preventionTips":["Pre-create and chown the parent volume root directory for the nomad client user during provisioning.","Ensure the requested volume path does not collide with existing files.","Keep volume paths on local POSIX filesystems, not read-only or exotic mounts.","Run the nomad client with sufficient privileges for the directories it must manage."],"tags":["filesystem","mkdir","permissions","host-volumes","go"],"backgroundTag":"mkdir-permission-denied","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"}