larksuite/cli · error
singleValue file provider expects ref id %q, got %q
Error message
singleValue file provider expects ref id %q, got %q
What it means
In singleValue mode the entire file content is the secret, so OpenClaw semantics require the SecretRef id to equal the sentinel SingleValueFileRefID. A different id means the config is inconsistent: the provider would otherwise silently ignore which id the caller asked for.
Source
Thrown at internal/binding/secret_resolve_file.go:77
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)
}
// Entire file content is the secret; trim trailing newline
return strings.TrimRight(content, "\r\n"), nil
case "json":
// Parse as JSON, then navigate via JSON Pointer (ref.ID)
var parsed interface{}
if err := json.Unmarshal(data, &parsed); err != nil {
return "", fmt.Errorf("file provider JSON parse error: %w", err)
}
value, err := ReadJSONPointer(parsed, ref.ID)
if err != nil {
return "", fmt.Errorf("file provider JSON Pointer %q: %w", ref.ID, err)
}
// Value must be a stringView on GitHub (pinned to 7fd6ef3c07)
Solutions
- Change the SecretRef id to SingleValueFileRefID when using singleValue mode.
- Or, if you need per-key lookup, switch ProviderConfig.Mode to "json" and keep your pointer id.
- Audit provider mode and ref id pairs in the binding config so they stay consistent.
Example fix
// before
{"source":"file","id":"/api_key"} // mode: singleValue
// after
{"source":"file","id":"SINGLE_VALUE_FILE_REF_ID"} // use the exported sentinel constant's value
// or set provider mode to "json" and keep the pointer id Defensive patterns
Strategy: validation
Validate before calling
if pc.Mode == "singleValue" && ref.ID != SingleValueFileRefID {
return fmt.Errorf("config error: singleValue mode requires ref id %q", SingleValueFileRefID)
} Try / catch
secret, err := resolveSecretRef(ctx, ref)
if err != nil {
if strings.Contains(err.Error(), "expects ref id") {
// fix the ref id or switch the provider mode to json
}
return err
} Prevention
- When switching a provider between json and singleValue, update every ref id in the same change.
- Centralize ref construction so the sentinel id is used for singleValue providers.
- Add a config lint that pairs mode with the expected ref id.
When it happens
Trigger: Calling resolveSecretRef with a {source:"file"} SecretRef whose ProviderConfig.Mode is "singleValue" but whose ref.ID is not SingleValueFileRefID (e.g. a leftover JSON-pointer-style id like "/api_key" from a json-mode config).
Common situations: Switching a provider from json to singleValue mode without updating the ref id; copying a ref from a json-mode provider; hand-writing the ref with an intuitive custom id.
Related errors
- file provider path is empty
- 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/000043c4e283890f.
Report an issue: GitHub.