larksuite/cli · error
failed to read secret file %s: %w
Error message
failed to read secret file %s: %w
What it means
The file provider could not read the secret file at the audited secure path via vfs.ReadFile. The OS-level error (not found, permission denied, is-a-directory, I/O error) is wrapped in this message along with the audited path.
Source
Thrown at internal/binding/secret_resolve_file.go:60
AllowReadableByOthers: false, // file provider: strict by default
AllowSymlinkPath: false,
})
if err != nil {
return "", fmt.Errorf("file provider security audit failed: %w", err)
}
// Read file content
maxBytes := pc.MaxBytes
if maxBytes <= 0 {
maxBytes = DefaultFileMaxBytes
}
// Note: vfs.ReadFile loads the entire file. maxBytes is enforced post-read
// because vfs does not expose a size-limited reader. For secret files this
// is acceptable (default limit 1 MiB; secrets are typically < 1 KB).
data, err := vfs.ReadFile(securePath)
if err != nil {
return "", fmt.Errorf("failed to read secret file %s: %w", securePath, err)
}
if len(data) > maxBytes {
return "", fmt.Errorf("file provider exceeded maxBytes (%d)", maxBytes)
}
content := string(data)
mode := pc.Mode
if mode == "" {
mode = "json" // default mode per OpenClaw
}
switch mode {
case "singleValue":
// OpenClaw requires ref.id == SINGLE_VALUE_FILE_REF_ID for singleValue mode
if ref.ID != SingleValueFileRefID {
return "", fmt.Errorf("singleValue file provider expects ref id %q, got %q",
SingleValueFileRefID, ref.ID)View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Verify the path in ProviderConfig.Path exists for the user running the process: `ls -l <path>`.
- Check read permissions for the process user (`chmod 600` and correct ownership via chown).
- Confirm ~ expands to the expected home (echo $HOME) — service/systemd contexts often differ from your shell.
- Recreate the file if it was rotated or moved; inspect the wrapped cause for the exact OS error.
Example fix
// before
path: ~/secrets/prod.json // file never created on this host
// after
mkdir -p ~/secrets && chmod 700 ~/secrets
printf '{"api_key":"..."}' > ~/secrets/prod.json && chmod 600 ~/secrets/prod.json Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := os.Stat(os.ExpandEnv(pc.Path)); err != nil {
return fmt.Errorf("secret file not accessible before resolve: %w", err)
} Try / catch
secret, err := resolveSecretRef(ctx, ref)
if err != nil {
if strings.Contains(err.Error(), "failed to read secret file") {
var perr *fs.PathError
if errors.As(err, &perr) && errors.Is(perr, fs.ErrNotExist) {
return fmt.Errorf("secret file missing at %s — create it or fix 'path'", perr.Path)
}
}
return err
} Prevention
- Provision the secret file (and permissions) as a deployment step before the process starts.
- Confirm $HOME in service/systemd/container contexts matches the configured ~ path.
- Use atomic writes so rotation never leaves the path temporarily missing.
When it happens
Trigger: Calling resolveSecretRef with a {source:"file"} SecretRef where the path passed the security audit but the read itself fails — file deleted between audit and read, wrong path after ~ expansion, running as a different user than the file owner, or the path is a directory.
Common situations: Typo in the configured path; the secret file was rotated/moved after config was written; `~` expansion points at a different home (e.g. under a service account or container); the file exists but the process user lacks read permission.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- file provider path is empty
- file provider security audit failed: %w
- file provider exceeded maxBytes (%d)
- singleValue file provider expects ref id %q, got %q
- file provider JSON parse error: %w
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/24f0c76590772652.
Report an issue: GitHub.