{"record":{"id":"4617f8574bc8bdbd","repo":"larksuite/cli","slug":"s-must-be-an-absolute-path-got-q","errorCode":null,"errorMessage":"%s must be an absolute path, got %q","messagePattern":"(.+?) must be an absolute path, got %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/vfs/localfileio/path.go","lineNumber":132,"sourceCode":"\t\treturn value, nil\n\t}\n\tif _, err := SafeInputPath(value); err != nil {\n\t\treturn \"\", fmt.Errorf(\"%s: %w\", flagName, err)\n\t}\n\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","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/vfs/localfileio/path.go#L114-L150","documentation":"SafeEnvDirPath validates an environment-provided application directory and requires the Cleaned value to be an absolute path. Relative paths are ambiguous across processes and working directories, so the function rejects them with the environment variable name and offending value.","triggerScenarios":"Calling SafeEnvDirPath with a relative value such as \"mydir\", \"./mydir\", or \"~/files\" (tilde is not expanded here) — typically from an env var like LARK_*_DIR set to a relative path, or a config template left unfilled.","commonSituations":"Env var set as `export APP_DIR=./data` in a script; a .env file with a relative default; a systemd unit with a relative Environment= value; user assuming ~ expansion happens.","solutions":["Set the environment variable to an absolute path: /home/user/mydir","Expand ~ yourself (or use $HOME) before setting the variable","Prefix with $(pwd) in shell when constructing the value at runtime"],"exampleFix":"# before\nexport LARK_APP_DIR=./myapp\n# error: LARK_APP_DIR must be an absolute path, got \"myapp\"\n# after\nexport LARK_APP_DIR=\"$PWD/myapp\"","handlingStrategy":"validation","validationCode":"if !filepath.IsAbs(filepath.Clean(v)) {\n    return fmt.Errorf(\"%s must be absolute, got %q\", envName, v)\n}","typeGuard":"func isAbsNoTilde(v string) bool {\n    return !strings.HasPrefix(v, \"~\") && filepath.IsAbs(filepath.Clean(v))\n}","tryCatchPattern":"dir, err := localfileio.SafeEnvDirPath(os.Getenv(\"MY_APP_DIR\"), \"MY_APP_DIR\")\nif err != nil {\n    return fmt.Errorf(\"fix the environment variable: %w\", err)\n}","preventionTips":["Set directory env vars with absolute paths ($PWD/mydir, not ./mydir)","Remember ~ is not expanded in env values; use $HOME","Validate .env and systemd Environment= values at startup"],"tags":["validation","path","environment-variable","absolute-path"],"backgroundTag":"relative-path-where-absolute-required","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"}