{"record":{"id":"62b9a49a8fc7bcf4","repo":"fatedier/frp","slug":"exec-configuration-is-required-when-type-is-exec","errorCode":null,"errorMessage":"exec configuration is required when type is 'exec'","messagePattern":"exec configuration is required when type is 'exec'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/value_source.go","lineNumber":65,"sourceCode":"\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\n\tswitch v.Type {\n\tcase \"file\":\n\t\treturn v.File.Resolve(ctx)\n\tcase \"exec\":\n\t\treturn v.Exec.Resolve(ctx)","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/value_source.go#L47-L83","documentation":"Thrown by ValueSource.Validate() in frp's config v1 package when a tokenSource (or other ValueSource) declares type: \"exec\" but the exec sub-object is missing. ValueSource is used to resolve auth tokens dynamically (pkg/config/v1/client.go TokenSource, server.go TokenSource). The switch dispatches validation to the matching sub-config; a nil Exec block cannot be validated.","triggerScenarios":"Setting tokenSource.type = \"exec\" in frpc.toml/frps.toml without a [tokenSource.exec] table; building a v1.ValueSource{Type: \"exec\"} literal in Go with Exec left nil; marshalling YAML/JSON that omits the exec key.","commonSituations":"Migrating a static auth.token to an exec-based token source and forgetting the command block; typos like type = \"Exec\" (case-sensitive, would hit the unsupported-type branch instead) or exEc; configs generated by templates that skip the exec section when a variable is empty.","solutions":["Add the exec block under tokenSource: [auth.tokenSource.exec] with command = \"...\" and optional args/env","If you meant to read a file, set type = \"file\" and provide a [auth.tokenSource.file] block with path","If constructing in Go, populate ValueSource{Type: \"exec\", Exec: &v1.ExecSource{Command: \"...\"}}","Run frpc verify -c ./frpc.toml (or frps verify) to validate before starting"],"exampleFix":"# before (frpc.toml)\n[auth]\ntokenSource.type = \"exec\"\n\n# after\n[auth]\ntokenSource.type = \"exec\"\n[auth.tokenSource.exec]\ncommand = \"/usr/local/bin/get-token\"\nargs = [\"--audience\", \"frps\"]","handlingStrategy":"validation","validationCode":"// Go: validate before use\nif vs := cfg.Auth.TokenSource; vs != nil {\n    if vs.Type == \"exec\" && vs.Exec == nil {\n        return fmt.Errorf(\"tokenSource.type=exec requires an exec block\")\n    }\n    if err := vs.Validate(); err != nil {\n        return err\n    }\n}","typeGuard":"func hasExecSource(vs *v1.ValueSource) bool {\n    return vs != nil && vs.Type == \"exec\" && vs.Exec != nil\n}","tryCatchPattern":null,"preventionTips":["Always run frpc/frps verify on config changes in CI before deploy","When templating configs, fail the template when an exec source has no command instead of emitting a half-filled block"],"tags":["frp","go","config","validation","auth"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}