{"record":{"id":"9e93b21c96fe9a86","repo":"larksuite/cli","slug":"account-has-no-home-directory","errorCode":null,"errorMessage":"account has no home directory","messagePattern":"account has no home directory","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/vfs/localfileio/policy.go","lineNumber":113,"sourceCode":"// guarantee. Release binaries are built with CGO_ENABLED=0, and pure-Go\n// os/user answers from $HOME for a uid the database does not list — distroless\n// images and `--user 99999` containers among them — as long as $USER is set\n// too; with $USER unset it returns an error instead and the ~/files root is\n// dropped altogether. Such an invocation does choose where ~/files points.\n// What that reaches is a directory named \"files\" under the path it names and\n// nothing else: the home directory itself is not an allow root, and denyRoots\n// covers every candidate home, so the credential directories stay protected\n// either way.\nvar trustedHome = sync.OnceValues(func() (string, error) {\n\tif home, ok := passwdHome(); ok {\n\t\treturn home, nil\n\t}\n\tu, err := user.Current()\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif u.HomeDir == \"\" {\n\t\treturn \"\", fmt.Errorf(\"account has no home directory\")\n\t}\n\treturn u.HomeDir, nil\n})\n\n// passwdHome reads this process's home directory straight out of the account\n// database, which no environment variable can influence. Reports false when\n// the file is absent (Windows, distroless) or holds no entry for the uid\n// (macOS keeps regular accounts in DirectoryService, not /etc/passwd).\nfunc passwdHome() (string, bool) {\n\tif runtime.GOOS == \"windows\" {\n\t\treturn \"\", false\n\t}\n\tf, err := vfs.Open(\"/etc/passwd\")\n\tif err != nil {\n\t\treturn \"\", false\n\t}\n\tdefer f.Close()\n","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/vfs/localfileio/policy.go#L95-L131","documentation":"The policy layer resolves '~' and similar roots from the current user account's home directory (user.Current().HomeDir). If the account database reports an empty HomeDir, no trustworthy home root exists, so the lookup fails rather than guessing a directory.","triggerScenarios":"Running under an account whose home directory is unset — e.g. a service account, a container user with no passwd entry fields, or an environment where user.Current() succeeds but HomeDir is empty — while the policy computes home-based allow/deny roots.","commonSituations":"Docker containers running as a bare UID with no /etc/passwd entry, Windows service accounts, or stripped-down CI users.","solutions":["Give the running account a home directory (create it and set it in the account database / passwd entry)","Set HOME (and USERPROFILE on Windows) to an existing directory — note this only helps paths that consult env vars, not this home lookup; prefer fixing the account","Run under a normal user account instead of a bare UID/no-home service account"],"exampleFix":"// before (Dockerfile)\nUSER 10001\n// after\nRUN useradd -m appuser\nUSER appuser","handlingStrategy":"fallback","validationCode":"u, err := user.Current()\nif err != nil || u.HomeDir == \"\" {\n\t// home unavailable: provision one before invoking the CLI\n}","typeGuard":"func hasHomeDir() bool {\n\tu, err := user.Current()\n\treturn err == nil && u.HomeDir != \"\"\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"account has no home directory\") {\n\t// fallback: set HOME/USERPROFILE or run under a provisioned user, then retry\n}","preventionTips":["Run containers with a real user created via useradd -m, not a bare numeric UID","Provision HOME/USERPROFILE in service and CI environments","Check `echo $HOME` (or USERPROFILE on Windows) resolves before running home-dependent commands"],"tags":["filesystem","environment","home-directory"],"backgroundTag":"missing-home-directory","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}