{"record":{"id":"fef4979b317f4513","repo":"fatedier/frp","slug":"file-configuration-is-required-when-type-is-file","errorCode":null,"errorMessage":"file configuration is required when type is 'file'","messagePattern":"file configuration is required when type is 'file'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/value_source.go","lineNumber":60,"sourceCode":"\tArgs    []string     `json:\"args,omitempty\"`\n\tEnv     []ExecEnvVar `json:\"env,omitempty\"`\n}\n\ntype ExecEnvVar struct {\n\tName  string `json:\"name\"`\n\tValue string `json:\"value\"`\n}\n\n// Validate validates the ValueSource configuration.\nfunc (v *ValueSource) Validate() error {\n\tif v == nil {\n\t\treturn errors.New(\"valueSource cannot be nil\")\n\t}\n\n\tswitch v.Type {\n\tcase \"file\":\n\t\tif v.File == nil {\n\t\t\treturn errors.New(\"file configuration is required when type is 'file'\")\n\t\t}\n\t\treturn v.File.Validate()\n\tcase \"exec\":\n\t\tif v.Exec == nil {\n\t\t\treturn errors.New(\"exec configuration is required when type is 'exec'\")\n\t\t}\n\t\treturn v.Exec.Validate()\n\tdefault:\n\t\treturn fmt.Errorf(\"unsupported value source type: %s (only 'file' and 'exec' are supported)\", v.Type)\n\t}\n}\n\n// Resolve resolves the value from the configured source.\nfunc (v *ValueSource) Resolve(ctx context.Context) (string, error) {\n\tif err := v.Validate(); err != nil {\n\t\treturn \"\", err\n\t}\n","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/value_source.go#L42-L78","documentation":"Validation error from ValueSource.Validate: the value source is declared with type \"file\" but its File sub-configuration is nil. ValueSource lets config fields (e.g. auth.token, oidc clientSecret) be read from a file or a command instead of a literal value; type \"file\" requires a matching {path: ...} object describing which file to read. The check runs whenever the config loader validates a ValueSource-typed field.","triggerScenarios":"A config field using value source syntax with type = \"file\" but no accompanying file block — e.g. {type = \"file\"} alone, or the file table nested under the wrong key so File decodes to nil. Also triggered in Go by constructing v1.ValueSource{Type: \"file\"} without setting File.","commonSituations":"Migrating secrets from literal strings to file-based sourcing and stopping halfway; YAML/TOML indentation errors putting the path key outside the file table; typo 'path' vs the expected key; JSON configs where \"file\": null.","solutions":["Supply the file block: {type = \"file\", file = {path = \"/run/secrets/token\"}} so File is non-nil.","Check indentation/nesting: the path key must live inside the file table, not beside type.","If the value should come from a command, use type = \"exec\" with exec = {command = [...]} instead.","Verify the referenced path exists and is readable by the frp process to avoid the later file-open failure."],"exampleFix":"# before\n[auth]\ntoken = {type = \"file\"}\n\n# after\n[auth]\ntoken = {type = \"file\", file = {path = \"/run/secrets/frp-token\"}}","handlingStrategy":"validation","validationCode":"func valueSourceWellFormed(vs *v1.ValueSource) error {\n    if vs == nil {\n        return nil // field not using a value source\n    }\n    switch vs.Type {\n    case \"file\":\n        if vs.File == nil {\n            return errors.New(\"type=file requires a file block with path\")\n        }\n    case \"exec\":\n        if vs.Exec == nil {\n            return errors.New(\"type=exec requires an exec block\")\n        }\n    }\n    return nil\n}","typeGuard":"func valueSourceComplete(vs v1.ValueSource) bool {\n    switch vs.Type {\n    case \"file\":\n        return vs.File != nil\n    case \"exec\":\n        return vs.Exec != nil\n    default:\n        return false\n    }\n}","tryCatchPattern":"if err := vs.Validate(); err != nil {\n    if strings.Contains(err.Error(), \"file configuration is required\") {\n        // add file = {path = ...} beside type = \"file\"\n    }\n    return err\n}","preventionTips":["Pair every type = \"file\" with file = {path = ...} in the same block.","Prefer TOML inline tables for value sources to keep them on one line.","Secret-sourcing changes should always be followed by frpc verify / frps verify."],"tags":["config","value-source","validation","secrets","file"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}