larksuite/cli · error
file provider path is empty
Error message
file provider path is empty
What it means
The file secret provider requires a filesystem path in its ProviderConfig, and none was supplied (pc.Path == ""). The resolver fails fast before attempting any file access or security audit, because there is no file to read for the secret.
Source
Thrown at internal/binding/secret_resolve_file.go:23
import (
"encoding/json"
"fmt"
"strings"
"github.com/larksuite/cli/internal/vfs"
)
// SingleValueFileRefID is the required ref.ID for singleValue file mode
// (aligned with OpenClaw ref-contract.ts SINGLE_VALUE_FILE_REF_ID).
const SingleValueFileRefID = "$SINGLE_VALUE"
// resolveFileRef handles {source:"file"} SecretRef resolution.
// Reads the file via assertSecurePath audit, then extracts the secret value
// based on the provider's mode (singleValue or json with JSON Pointer).
func resolveFileRef(ref *SecretRef, pc *ProviderConfig) (string, error) {
if pc.Path == "" {
return "", fmt.Errorf("file provider path is empty")
}
// OpenClaw preserves user-authored `~/...` paths verbatim on disk for
// portability and resolves them at read time. lark-cli reads the file
// raw, so we mirror that resolution here before the audit — otherwise
// an unambiguous home-relative path would be rejected by
// requireAbsolutePath, which is meant to guard against cwd-relative
// paths (a different concern). expandTildePath honours OPENCLAW_HOME so
// a tilde inside an OPENCLAW_HOME-overridden config resolves to the
// same absolute path OpenClaw itself would have used.
targetPath := expandTildePath(pc.Path)
// Security audit on file path
securePath, err := AssertSecurePath(AuditParams{
TargetPath: targetPath,
Label: "secrets.providers file path",
TrustedDirs: pc.TrustedDirs,
AllowInsecurePath: pc.AllowInsecurePath,View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Set ProviderConfig.Path to the secret file location in the provider config.
- Check the config file/env source that populates Path — a missing or empty variable likely interpolated to "".
- Add startup validation of the binding config so an empty path is rejected before secret resolution.
Example fix
// before
providers:
mysecret:
source: file
# path missing
// after
providers:
mysecret:
source: file
path: ~/.config/myapp/secrets.json Defensive patterns
Strategy: validation
Validate before calling
if pc.Source == "file" && pc.Path == "" {
return fmt.Errorf("file provider %q requires a non-empty path", name)
} Type guard
func hasFilePath(pc *ProviderConfig) bool { return pc != nil && pc.Path != "" } Try / catch
secret, err := resolveSecretRef(ctx, ref)
if err != nil {
if strings.Contains(err.Error(), "path is empty") {
return fmt.Errorf("check provider config: file source needs 'path'")
}
return err
} Prevention
- Validate the full provider config (source, path, mode) at startup before any resolution.
- Avoid interpolating optional env vars into path without a fallback.
- Add a config schema check that marks `path` required when source is file.
When it happens
Trigger: Calling resolveSecretRef with a {source:"file"} SecretRef whose ProviderConfig has Path set to the empty string, or the provider config was constructed/decoded without the path field.
Common situations: A YAML/JSON binding config omits the `path` key for the file provider; an env var feeding the path was unset so the config interpolated to ""; a refactor renamed the field so the value no longer populates Path.
Related errors
- singleValue file provider expects ref id %q, got %q
- unsupported file provider mode %q
- file provider JSON Pointer %q: %w
- SecretRef.source must be env|file|exec, got %q
- SecretRef.id must be non-empty
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/a72f1416243a8f7e.
Report an issue: GitHub.