larksuite/cli · error
cannot expand ~: %w
Error message
cannot expand ~: %w
What it means
This error is produced by `absolutize` when a path argument starts with `~` or `~/` but the user's home directory cannot be determined (via trustedHome). The tilde cannot be expanded, so the absolute location needed for policy checks cannot be computed. Unlike error 510, this is the raw inner error before the flag-name wrapper.
Source
Thrown at internal/vfs/localfileio/path.go:260
// absolutize expands a leading ~/ to the user home directory and roots
// relative paths at cwd, exactly as this platform's own path rules would. The
// result is Cleaned but not symlink-resolved.
//
// Joining is decided by filepath.IsAbs alone, so the location computed here is
// the location the OS will actually open. A shape that only looks absolute
// under foreign rules (`C:\x` or `\x` on Unix) is a relative path here, and
// resolving it as such is what lets the denylist see through it — a cwd-local
// symlink named `C:` would otherwise carry it anywhere.
//
// raw is used as given: trailing and leading spaces are legal in filenames, so
// trimming them here would silently address a different file than the caller
// named (emptiness is screened separately, before this call).
func absolutize(raw, cwd string) (string, error) {
p := raw
if p == "~" || strings.HasPrefix(p, "~/") {
home, err := trustedHome()
if err != nil {
return "", fmt.Errorf("cannot expand ~: %w", err)
}
p = filepath.Join(home, strings.TrimPrefix(p, "~"))
}
if !filepath.IsAbs(p) {
p = filepath.Join(cwd, p)
}
return filepath.Clean(p), nil
}
// rejectForeignAbsolute refuses a path that is absolute only under another
// platform's rules. The strict tier rejects the shape outright rather than
// silently treating it as a relative name, which is a confusing way to grant
// access; the relaxed tier keeps such paths verbatim by contract and instead
// gets the denylist applied to the location the OS would really open.
func rejectForeignAbsolute(raw, flagName string) error {
if isAbsolutePath(raw) && !filepath.IsAbs(raw) {
return fmt.Errorf("%s %q is not a valid path on this platform", flagName, raw)
}View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Set the HOME environment variable before invoking the command.
- Replace the ~/... path with an explicit absolute path.
- Run the command as an interactive user with a home directory.
Example fix
// before lark-cli drive upload --file ~/files/data.csv # HOME not set // after HOME=/home/alice lark-cli drive upload --file ~/files/data.csv
Defensive patterns
Strategy: validation
Validate before calling
// Shell: fail fast if HOME is missing before any ~ path is used
: "${HOME:?HOME is not set; cannot use ~ paths}" Prevention
- Set HOME explicitly in cron, systemd units, and Dockerfiles.
- In service accounts on Windows, avoid ~ paths entirely; use absolute paths.
- Document the HOME requirement next to any command using ~/files.
When it happens
Trigger: Passing `~` or `~/...` to SafeInputPath/SafeOutputPath (or denyCheckLocalInput via LocalInputPath) when os.UserHomeDir fails: $HOME unset on Unix, no user profile on Windows, or running under a system account.
Common situations: Cron jobs, systemd services, Docker containers, and CI workers where HOME is not set; Windows service accounts without a loaded profile.
Related errors
- No visible worksheet matched
- %s: path must be absolute, got %q
- %s: path %q is a directory, not a file
- %q has invalid relative path %q
- %s %q resolves outside the current working directory (hint:
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/48bc203595994706.
Report an issue: GitHub.