larksuite/cli · error

%s must be an absolute path, got %q

Error message

%s must be an absolute path, got %q

What it means

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.

Source

Thrown at internal/vfs/localfileio/path.go:132

		return value, nil
	}
	if _, err := SafeInputPath(value); err != nil {
		return "", fmt.Errorf("%s: %w", flagName, err)
	}
	return value, nil
}

// SafeEnvDirPath validates an environment-provided application directory path.
// It requires an absolute path, rejects control characters, normalizes the
// input, and resolves symlinks through the nearest existing ancestor.
func SafeEnvDirPath(path, envName string) (string, error) {
	if err := charcheck.RejectControlChars(path, envName); err != nil {
		return "", err
	}

	path = filepath.Clean(path)
	if !filepath.IsAbs(path) {
		return "", fmt.Errorf("%s must be an absolute path, got %q", envName, path)
	}

	resolved, err := resolveNearestAncestor(path)
	if err != nil {
		return "", fmt.Errorf("cannot resolve symlinks: %w", err)
	}
	return resolved, nil
}

// safePath is the shared implementation for SafeOutputPath and SafeInputPath.
// A path is accepted when its real location falls inside the built-in
// allowlist (cwd, /tmp, ~/files) and outside the built-in denylist; deny wins
// over allow, cwd included. Both lists are compiled in (policy.go), which
// also documents the two bounded environment inputs that remain.
func safePath(raw, flagName string) (string, error) {
	isOutputFlag := flagName == "--output"
	if err := charcheck.RejectControlChars(raw, flagName); err != nil {
		return "", err

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Set the environment variable to an absolute path: /home/user/mydir
  2. Expand ~ yourself (or use $HOME) before setting the variable
  3. Prefix with $(pwd) in shell when constructing the value at runtime

Example fix

# before
export LARK_APP_DIR=./myapp
# error: LARK_APP_DIR must be an absolute path, got "myapp"
# after
export LARK_APP_DIR="$PWD/myapp"
Defensive patterns

Strategy: validation

Validate before calling

if !filepath.IsAbs(filepath.Clean(v)) {
    return fmt.Errorf("%s must be absolute, got %q", envName, v)
}

Type guard

func isAbsNoTilde(v string) bool {
    return !strings.HasPrefix(v, "~") && filepath.IsAbs(filepath.Clean(v))
}

Try / catch

dir, err := localfileio.SafeEnvDirPath(os.Getenv("MY_APP_DIR"), "MY_APP_DIR")
if err != nil {
    return fmt.Errorf("fix the environment variable: %w", err)
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/4617f8574bc8bdbd. Report an issue: GitHub.