{"record":{"id":"a72f1416243a8f7e","repo":"larksuite/cli","slug":"file-provider-path-is-empty","errorCode":null,"errorMessage":"file provider path is empty","messagePattern":"file provider path is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/binding/secret_resolve_file.go","lineNumber":23,"sourceCode":"\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n\n\t\"github.com/larksuite/cli/internal/vfs\"\n)\n\n// SingleValueFileRefID is the required ref.ID for singleValue file mode\n// (aligned with OpenClaw ref-contract.ts SINGLE_VALUE_FILE_REF_ID).\nconst SingleValueFileRefID = \"$SINGLE_VALUE\"\n\n// resolveFileRef handles {source:\"file\"} SecretRef resolution.\n// Reads the file via assertSecurePath audit, then extracts the secret value\n// based on the provider's mode (singleValue or json with JSON Pointer).\nfunc resolveFileRef(ref *SecretRef, pc *ProviderConfig) (string, error) {\n\tif pc.Path == \"\" {\n\t\treturn \"\", fmt.Errorf(\"file provider path is empty\")\n\t}\n\n\t// OpenClaw preserves user-authored `~/...` paths verbatim on disk for\n\t// portability and resolves them at read time. lark-cli reads the file\n\t// raw, so we mirror that resolution here before the audit — otherwise\n\t// an unambiguous home-relative path would be rejected by\n\t// requireAbsolutePath, which is meant to guard against cwd-relative\n\t// paths (a different concern). expandTildePath honours OPENCLAW_HOME so\n\t// a tilde inside an OPENCLAW_HOME-overridden config resolves to the\n\t// same absolute path OpenClaw itself would have used.\n\ttargetPath := expandTildePath(pc.Path)\n\n\t// Security audit on file path\n\tsecurePath, err := AssertSecurePath(AuditParams{\n\t\tTargetPath:            targetPath,\n\t\tLabel:                 \"secrets.providers file path\",\n\t\tTrustedDirs:           pc.TrustedDirs,\n\t\tAllowInsecurePath:     pc.AllowInsecurePath,","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/larksuite/cli/blob/7fd6ef3c07182257ce776cdc5a614e122d5bd4b3/internal/binding/secret_resolve_file.go#L5-L41","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nproviders:\n  mysecret:\n    source: file\n    # path missing\n// after\nproviders:\n  mysecret:\n    source: file\n    path: ~/.config/myapp/secrets.json","handlingStrategy":"validation","validationCode":"if pc.Source == \"file\" && pc.Path == \"\" {\n    return fmt.Errorf(\"file provider %q requires a non-empty path\", name)\n}","typeGuard":"func hasFilePath(pc *ProviderConfig) bool { return pc != nil && pc.Path != \"\" }","tryCatchPattern":"secret, err := resolveSecretRef(ctx, ref)\nif err != nil {\n    if strings.Contains(err.Error(), \"path is empty\") {\n        return fmt.Errorf(\"check provider config: file source needs 'path'\")\n    }\n    return err\n}","preventionTips":["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."],"tags":["secrets","file-provider","config","validation"],"backgroundTag":"missing-config-field","analyzedSha":"7fd6ef3c07182257ce776cdc5a614e122d5bd4b3","analyzedAt":"2026-09-04T21:17:44.649Z","contentChangedAt":"2026-09-04T21:17:44.649Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}