{"record":{"id":"c67f9e72a8d4805f","repo":"hashicorp/nomad","slug":"unable-to-set-permissions-on-unix-socket-w","errorCode":null,"errorMessage":"unable to set permissions on unix socket: %w","messagePattern":"unable to set permissions on unix socket: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/allocrunner/consul_http_sock_hook.go","lineNumber":236,"sourceCode":"\t\tsocketFile = filepath.Join(allocdir.SharedAllocName, allocdir.TmpDirName,\n\t\t\t\"consul_\"+p.config.Name+\"_http.sock\")\n\t}\n\thostHTTPSockPath := filepath.Join(p.allocDir.AllocDirPath(), socketFile)\n\tif err := maybeRemoveOldSocket(hostHTTPSockPath); err != nil {\n\t\treturn err\n\t}\n\n\tlistener, err := net.Listen(\"unix\", hostHTTPSockPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to create unix socket for Consul HTTP endpoint: %w\", err)\n\t}\n\n\t// The Consul HTTP socket should be usable by all users in case a task is\n\t// running as a non-privileged user. Unix does not allow setting domain\n\t// socket permissions when creating the file, so we must manually call\n\t// chmod afterwards.\n\tif err := os.Chmod(hostHTTPSockPath, os.ModePerm); err != nil {\n\t\treturn fmt.Errorf(\"unable to set permissions on unix socket: %w\", err)\n\t}\n\n\tgo func() {\n\t\tproxy(p.ctx, p.logger, destAddr, listener)\n\t\tp.cancel()\n\t\tclose(p.doneCh)\n\t}()\n\n\tp.runOnce = true\n\treturn nil\n}\n\nfunc (p *httpSocketProxy) stop() error {\n\tp.cancel()\n\n\t// if proxy was never run, no need to wait before shutdown\n\tif !p.runOnce {\n\t\treturn nil","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/client/allocrunner/consul_http_sock_hook.go#L218-L254","documentation":"After creating the Consul HTTP unix socket, the hook chmods it to os.ModePerm (0777) so non-root task users can connect to the Consul HTTP API through the alloc's network namespace. If os.Chmod fails (usually a permissions or filesystem issue on the socket path), the socket would be unusable by unprivileged tasks, so the hook aborts with this wrapped error.","triggerScenarios":"run() successfully creates the listener at hostHTTPSockPath but os.Chmod(hostHTTPSockPath, os.ModePerm) returns an error — e.g. the file was removed between listen and chmod, the client runs as an unprivileged user not owning the socket, or the filesystem disallows chmod.","commonSituations":"Nomad client agent running as a non-root user without ownership of the socket path; unusual filesystems (some network mounts) rejecting chmod on sockets; security software or containers mounting paths with restricted chmod; race where the socket file is deleted concurrently.","solutions":["Run the Nomad client as root (or a user with ownership of the host_http_socket path) so chmod succeeds","Check the wrapped OS error: EPERM → fix ownership of hostHTTPSockPath's directory; ENOENT → investigate concurrent deletion","Move the client data_dir / socket path to a local filesystem (ext4/xfs) that supports chmod on sockets","Restart the alloc to recreate the socket and retry chmod"],"exampleFix":"// before\nif err := os.Chmod(hostHTTPSockPath, os.ModePerm); err != nil {\n\treturn fmt.Errorf(\"unable to set permissions on unix socket: %w\", err)\n}\n\n// after: tolerate already-removed socket\nif err := os.Chmod(hostHTTPSockPath, os.ModePerm); err != nil {\n\tif _, statErr := os.Lstat(hostHTTPSockPath); os.IsNotExist(statErr) {\n\t\treturn errSocketRemoved\n\t}\n\treturn fmt.Errorf(\"unable to set permissions on unix socket: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"// verify we can chmod in the socket directory before creating the listener\nsockDir := filepath.Dir(hostHTTPSockPath)\nprobe := filepath.Join(sockDir, \".chmodprobe\")\nif err := os.WriteFile(probe, nil, 0o777); err != nil {\n\treturn fmt.Errorf(\"cannot manage permissions in %s: %w\", sockDir, err)\n}\nos.Remove(probe)","typeGuard":null,"tryCatchPattern":"if err := os.Chmod(hostHTTPSockPath, os.ModePerm); err != nil {\n\tswitch {\n\tcase errors.Is(err, os.ErrPermission):\n\t\t// client lacks ownership; escalate/restart agent as root\n\tcase errors.Is(err, os.ErrNotExist):\n\t\t// socket removed concurrently; recreate listener\n\t}\n\treturn fmt.Errorf(\"unable to set permissions on unix socket: %w\", err)\n}","preventionTips":["Run the Nomad client agent as root or a user owning the host_http_socket path","Avoid mounting the client data_dir from network filesystems that restrict chmod","Verify no external security tooling strips/changes socket file modes","Monitor for EPERM/ENOENT in the wrapped error to distinguish ownership vs race issues"],"tags":["consul","unix-socket","permissions","chmod"],"backgroundTag":"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"}