{"record":{"id":"0053d5b33486e5ca","repo":"larksuite/cli","slug":"cannot-resolve-symlinks-w","errorCode":null,"errorMessage":"cannot resolve symlinks: %w","messagePattern":"cannot resolve symlinks: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/vfs/localfileio/path.go","lineNumber":137,"sourceCode":"\treturn value, nil\n}\n\n// SafeEnvDirPath validates an environment-provided application directory path.\n// It requires an absolute path, rejects control characters, normalizes the\n// input, and resolves symlinks through the nearest existing ancestor.\nfunc SafeEnvDirPath(path, envName string) (string, error) {\n\tif err := charcheck.RejectControlChars(path, envName); err != nil {\n\t\treturn \"\", err\n\t}\n\n\tpath = filepath.Clean(path)\n\tif !filepath.IsAbs(path) {\n\t\treturn \"\", fmt.Errorf(\"%s must be an absolute path, got %q\", envName, path)\n\t}\n\n\tresolved, err := resolveNearestAncestor(path)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"cannot resolve symlinks: %w\", err)\n\t}\n\treturn resolved, nil\n}\n\n// safePath is the shared implementation for SafeOutputPath and SafeInputPath.\n// A path is accepted when its real location falls inside the built-in\n// allowlist (cwd, /tmp, ~/files) and outside the built-in denylist; deny wins\n// over allow, cwd included. Both lists are compiled in (policy.go), which\n// also documents the two bounded environment inputs that remain.\nfunc safePath(raw, flagName string) (string, error) {\n\tisOutputFlag := flagName == \"--output\"\n\tif err := charcheck.RejectControlChars(raw, flagName); err != nil {\n\t\treturn \"\", err\n\t}\n\tif strings.TrimSpace(raw) == \"\" {\n\t\treturn \"\", fmt.Errorf(\"%s must not be empty\", flagName)\n\t}\n\tif err := validatePathPlatform(raw); err != nil {","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/vfs/localfileio/path.go#L119-L155","documentation":"SafeEnvDirPath resolves symlinks through the nearest existing ancestor of the directory. If Lstat/EvalSymlinks on that ancestor chain fails (permission denied on a component, I/O error, or a symlink loop the resolver cannot evaluate), the function fails closed and wraps the OS error with this message.","triggerScenarios":"Calling SafeEnvDirPath where resolveNearestAncestor hits an unreadable parent directory (EACCES), a symlink cycle, or a stale automount/NFS mount point on the path.","commonSituations":"Env var pointing into another user's home with no search permission; a broken symlink loop in the ancestor chain; network mounts that dropped; paths under /media or automounted dirs that are currently offline.","solutions":["Check permissions on each path component: `namei -l /the/path` and fix with chmod/chown","Inspect the chain for symlink loops: `ls -la` each component and remove the offending link","Verify the mount is active (mount / df) if the path lives on a network or automounted volume","Point the env var at a simpler path without symlinks"],"exampleFix":"# before\nexport LARK_APP_DIR=/mnt/nfs/app   # NFS server down\n# error: cannot resolve symlinks: lstat /mnt/nfs: no such file or directory\n# after (mount recovered) or:\nexport LARK_APP_DIR=/opt/local/app","handlingStrategy":"fallback","validationCode":"if _, err := filepath.EvalSymlinks(existingPrefix(v)); err != nil {\n    return fmt.Errorf(\"cannot resolve %q: %w\", v, err)\n}","typeGuard":null,"tryCatchPattern":"dir, err := localfileio.SafeEnvDirPath(os.Getenv(\"MY_APP_DIR\"), \"MY_APP_DIR\")\nif err != nil && strings.Contains(err.Error(), \"cannot resolve symlinks\") {\n    dir = fallbackDir // e.g. \"/opt/myapp\"\n}","preventionTips":["Check component permissions with namei -l when paths fail","Avoid symlink loops and stale network mount points in configured paths","Prefer plain, symlink-free directories for app state"],"tags":["filesystem","symlink","environment-variable","permissions"],"backgroundTag":"symlink-resolution-failed","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"}