larksuite/cli · error
%s must not be empty
Error message
%s must not be empty
What it means
safePath (shared by SafeOutputPath and SafeInputPath) rejects a value that is empty or whitespace-only after the control-character check, prefixing the message with the flag name. An empty path can never satisfy the allowlist policy, so it fails early with a clear message.
Source
Thrown at internal/vfs/localfileio/path.go:153
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
}
if strings.TrimSpace(raw) == "" {
return "", fmt.Errorf("%s must not be empty", flagName)
}
if err := validatePathPlatform(raw); err != nil {
return "", fmt.Errorf("%s: %w", flagName, err)
}
if err := rejectForeignAbsolute(raw, flagName); err != nil {
return "", err
}
cwd, err := vfs.Getwd()
if err != nil {
return "", fmt.Errorf("cannot determine working directory: %w", err)
}
// Every reading of the argument must pass, not just the one this function
// returns: callers that keep the original string (SafeLocalFlagPath does)
// open the location the OS computes, and for a "~/..." argument that is a
// literal "~" entry in the working directory rather than the home
// directory. A path is only safe when both readings are.
interps, err := interpretations(raw, cwd)View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Provide a concrete value for the flag before invoking the command
- Guard in shell: `: "${OUTPUT:?OUTPUT not set}"` before running
- Fix the templating/config so the placeholder is actually filled
Example fix
// before
cmd.Flags().String("output", cfg.Output, "") // cfg.Output == ""
// error: --output must not be empty
// after
if cfg.Output == "" {
cfg.Output = "./out.bin"
}
cmd.Flags().String("output", cfg.Output, "") Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(out) == "" {
return errors.New("--output is required")
} Type guard
func hasOutputPath(v string) bool { return strings.TrimSpace(v) != "" } Try / catch
if _, err := localfileio.SafeOutputPath(flagValue); err != nil {
return fmt.Errorf("--output: %w", err)
} Prevention
- Provide defaults for output flags in config
- Guard shell variables with ${OUT:?msg}
- Verify templating placeholders are substituted before exec
When it happens
Trigger: Calling SafeOutputPath("") or SafeInputPath(" ") — an --output/--file flag bound to an unset variable, an empty config field, or a templating placeholder like {{output}} left unsubstituted.
Common situations: Script variable $OUT never set; YAML/JSON config with an empty string value; templated command where the substitution failed; shell ${VAR} expanding to empty because an earlier step produced no output.
Related errors
- local input path must not be empty
- %s: %w
- local input path must not contain control characters
- %s must be an absolute path, got %q
- Invalid column: {column!r}
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/e3e6403c94756c24.
Report an issue: GitHub.