larksuite/cli · error
%s: %w
Error message
%s: %w
What it means
SafeLocalFlagPath validates a flag value as a local file path by delegating to SafeInputPath; on failure it prefixes the error with the flag name. Empty values and http/https URLs bypass validation entirely, so this fires only for non-URL local path values that fail the strict path policy.
Source
Thrown at internal/vfs/localfileio/path.go:117
return err
}
}
return nil
}
func isWindowsNonLocalNamespace(path string) bool {
normalized := strings.ReplaceAll(path, "/", `\`)
return strings.HasPrefix(normalized, `\\`) || strings.HasPrefix(normalized, `\??\`)
}
// SafeLocalFlagPath validates a flag value as a local file path.
// Empty values and http/https URLs are returned unchanged without validation.
func SafeLocalFlagPath(flagName, value string) (string, error) {
if value == "" || strings.HasPrefix(value, "http://") || strings.HasPrefix(value, "https://") {
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)View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Read the wrapped %w cause to see which policy check failed and move the file accordingly (cwd, /tmp, or ~/files)
- If the value is a URL, use an http:// or https:// URL (those bypass path validation)
- Use a relative path that stays inside the current working directory
- If the file must come from anywhere, pass it via stdin ("-") instead of a path
Example fix
// before lark cmd --attachment /etc/hosts // error: --attachment: --file "/etc/hosts" resolves outside the allowed roots // after cp /etc/hosts /tmp/hosts.txt && lark cmd --attachment /tmp/hosts.txt
Defensive patterns
Strategy: validation
Validate before calling
if v != "" && !strings.HasPrefix(v, "http://") && !strings.HasPrefix(v, "https://") {
if _, err := os.Stat(v); err != nil {
return fmt.Errorf("%s: local file %q unavailable: %w", flag, v, err)
}
} Type guard
func isHTTPURL(v string) bool {
return strings.HasPrefix(v, "http://") || strings.HasPrefix(v, "https://")
} Try / catch
if _, err := localfileio.SafeLocalFlagPath("--file", v); err != nil {
var pathErr *os.PathError
if errors.As(err, &pathErr) { /* fix path */ }
return fmt.Errorf("%w (allowed roots: cwd, /tmp, ~/files)", err)
} Prevention
- Keep input files inside cwd, /tmp, or ~/files
- Use http(s) URLs for remote content, local paths otherwise
- Avoid Windows-style paths on Unix and vice versa
When it happens
Trigger: Calling SafeLocalFlagPath(flagName, value) where value is a non-empty local (non-http/https) string that SafeInputPath rejects — outside the allowlist, containing control characters, a foreign absolute path like C:\x on Unix, a ~/ literal reading outside the policy, etc.
Common situations: Passing a file:// or other scheme URL that isn't http/https; passing a Windows path on Linux; pointing at a file outside cwd, /tmp, or ~/files; a flag intended for a URL given a local path.
Related errors
- %s must not be empty
- plugin %q rule invalid: %w
- policy yaml %q: %w
- invalid max_risk %q: must be one of read|write|high-risk-wri
- local input path must not be empty
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/7891800dd0817419.
Report an issue: GitHub.