{"record":{"id":"7bd62b25b723710a","repo":"fatedier/frp","slug":"cannot-specify-both-auth-token-and-auth-tokensourc","errorCode":null,"errorMessage":"cannot specify both auth.token and auth.tokenSource","messagePattern":"cannot specify both auth\\.token and auth\\.tokenSource","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/config/v1/validation/auth.go","lineNumber":28,"sourceCode":"// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\npackage validation\n\nimport (\n\t\"fmt\"\n\n\tv1 \"github.com/fatedier/frp/pkg/config/v1\"\n\t\"github.com/fatedier/frp/pkg/policy/security\"\n)\n\nfunc (v *ConfigValidator) validateAuthTokenSource(token string, tokenSource *v1.ValueSource) error {\n\tvar errs error\n\t// Preserve the previous client/server validation order for joined errors.\n\tif token != \"\" && tokenSource != nil {\n\t\terrs = AppendError(errs, fmt.Errorf(\"cannot specify both auth.token and auth.tokenSource\"))\n\t}\n\tif tokenSource == nil {\n\t\treturn errs\n\t}\n\n\tif tokenSource.Type == \"exec\" {\n\t\tif err := v.ValidateUnsafeFeature(security.TokenSourceExec); err != nil {\n\t\t\terrs = AppendError(errs, err)\n\t\t}\n\t}\n\tif err := tokenSource.Validate(); err != nil {\n\t\terrs = AppendError(errs, fmt.Errorf(\"invalid auth.tokenSource: %v\", err))\n\t}\n\treturn errs\n}\n","sourceCodeStart":10,"sourceCodeEnd":44,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/pkg/config/v1/validation/auth.go#L10-L44","documentation":"The v1 ConfigValidator's validateAuthTokenSource rejects configs that set both auth.token (a literal token string) and auth.tokenSource (a structured external token provider). The two are mutually exclusive ways to supply the auth token, so specifying both is a configuration contradiction and fails validation before the client or server starts.","triggerScenarios":"Running config validation (client load or server load path) with a config containing e.g. [auth] token = \"abc\" and [auth.tokenSource] type = \"file\" ... — any non-empty token plus a non-nil tokenSource triggers it. The check fires before tokenSource content is validated.","commonSituations":"Migrating from static token to tokenSource and forgetting to delete the old token line; templated configs that always emit a default token while also mounting a token source; merging includes/shared snippets that each contribute one of the fields.","solutions":["Delete one of the two: keep auth.token for static tokens, or keep auth.tokenSource for external sources.","If migrating to tokenSource, remove the literal token from the config and any secret-injection default that fills it.","Audit included/merged config fragments so only one auth supply mechanism survives the merge."],"exampleFix":"# before\n[auth]\ntoken = \"abc123\"\n[auth.tokenSource]\ntype = \"file\"\npath = \"/run/secrets/token\"\n\n# after\n[auth.tokenSource]\ntype = \"file\"\npath = \"/run/secrets/token\"","handlingStrategy":"validation","validationCode":"// Reject configs that set both token and tokenSource before loading.\nfunc authNotConflicting(token string, tokenSource *v1.ValueSource) error {\n\tif token != \"\" && tokenSource != nil {\n\t\treturn fmt.Errorf(\"set either auth.token or auth.tokenSource, not both\")\n\t}\n\treturn nil\n}","typeGuard":"func hasSingleAuthSource(token string, tokenSource *v1.ValueSource) bool {\n\treturn token == \"\" || tokenSource == nil\n}","tryCatchPattern":null,"preventionTips":["When migrating to tokenSource, delete the literal token in the same change.","Make sure default/templated token values don't merge with a tokenSource block.","Run frpc verify after auth changes."],"tags":["go","frp","config","auth","validation"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}