{"record":{"id":"5260ca0e1cfe43c0","repo":"fatedier/frp","slug":"failed-to-read-file-s-v","errorCode":null,"errorMessage":"failed to read file %s: %v","messagePattern":"failed to read file (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/value_source.go","lineNumber":109,"sourceCode":"\tif f == nil {\n\t\treturn errors.New(\"fileSource cannot be nil\")\n\t}\n\n\tif f.Path == \"\" {\n\t\treturn errors.New(\"file path cannot be empty\")\n\t}\n\treturn nil\n}\n\n// Resolve reads and returns the content from the specified file.\nfunc (f *FileSource) Resolve(_ context.Context) (string, error) {\n\tif err := f.Validate(); err != nil {\n\t\treturn \"\", err\n\t}\n\n\tcontent, err := os.ReadFile(f.Path)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to read file %s: %v\", f.Path, err)\n\t}\n\n\t// Trim whitespace, which is important for file-based tokens\n\treturn strings.TrimSpace(string(content)), nil\n}\n\n// Validate validates the ExecSource configuration.\nfunc (e *ExecSource) Validate() error {\n\tif e == nil {\n\t\treturn errors.New(\"execSource cannot be nil\")\n\t}\n\n\tif e.Command == \"\" {\n\t\treturn errors.New(\"exec command cannot be empty\")\n\t}\n\n\tfor _, env := range e.Env {\n\t\tif env.Name == \"\" {","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/value_source.go#L91-L127","documentation":"FileSource.Resolve() wraps the os.ReadFile error when the configured path cannot be read. The underlying error (permissions, missing file, path too long, etc.) is preserved with %v, so the message tells you both which file failed and why. Content is trimmed of surrounding whitespace, so a token file with a trailing newline is fine.","triggerScenarios":"ValueSource{Type: \"file\"}.Resolve(ctx) where the path does not exist, is a directory, or is not readable by the frp process user; also triggered by a symlink loop or a path on an unmounted volume at startup.","commonSituations":"Docker/Kubernetes: token file not mounted into the container, or mounted at a different path than configured; file permissions 0600 owned by root while frpc runs as a non-root user; secret (e.g. a Vault-injected token file) not yet written when frp starts; relative path resolved against a different working directory.","solutions":["Verify the file exists and is readable: ls -l /path/to/file and run frp as a user with read permission.","Use an absolute path in file.path to avoid working-directory surprises.","If the file is injected asynchronously (sidecar, Vault agent), make frp start after the file exists (initContainer, systemd dependency) — there is no retry built in.","In containers, double-check the mount target matches file.path exactly."],"exampleFix":"# before (frpc.toml)\n[auth.token.valueSource]\ntype = \"file\"\nfile.path = \"token.txt\"   # relative; missing in container\n\n# after\ntype = \"file\"\nfile.path = \"/etc/frp/token.txt\"   # absolute, mounted read-only","handlingStrategy":"try-catch","validationCode":"func fileReadable(path string) error {\n\tinfo, err := os.Stat(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif info.IsDir() {\n\t\treturn fmt.Errorf(\"%s is a directory\", path)\n\t}\n\tf, err := os.Open(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\treturn f.Close()\n}","typeGuard":null,"tryCatchPattern":"val, err := vs.Resolve(ctx)\nif err != nil {\n\tif strings.HasPrefix(err.Error(), \"failed to read file\") {\n\t\t// config/startup error: report path and fix mount or permissions; do not retry blindly\n\t\tlog.Fatalf(\"value source file unreadable: %v\", err)\n\t}\n\treturn err\n}","preventionTips":["Use absolute paths for token files.","Add a startup readiness probe that checks the token file exists and is readable.","In containers, verify the mount path matches file.path and the frp user can read it."],"tags":["filesystem","config","frp","permissions","docker"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}