fatedier/frp · error
cannot specify both auth.token and auth.tokenSource
Error message
cannot specify both auth.token and auth.tokenSource
What it means
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.
Source
Thrown at pkg/config/v1/validation/auth.go:28
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validation
import (
"fmt"
v1 "github.com/fatedier/frp/pkg/config/v1"
"github.com/fatedier/frp/pkg/policy/security"
)
func (v *ConfigValidator) validateAuthTokenSource(token string, tokenSource *v1.ValueSource) error {
var errs error
// Preserve the previous client/server validation order for joined errors.
if token != "" && tokenSource != nil {
errs = AppendError(errs, fmt.Errorf("cannot specify both auth.token and auth.tokenSource"))
}
if tokenSource == nil {
return errs
}
if tokenSource.Type == "exec" {
if err := v.ValidateUnsafeFeature(security.TokenSourceExec); err != nil {
errs = AppendError(errs, err)
}
}
if err := tokenSource.Validate(); err != nil {
errs = AppendError(errs, fmt.Errorf("invalid auth.tokenSource: %v", err))
}
return errs
}
View on GitHub (pinned to 6c8a8d0a97)
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.
Example fix
# before [auth] token = "abc123" [auth.tokenSource] type = "file" path = "/run/secrets/token" # after [auth.tokenSource] type = "file" path = "/run/secrets/token"
Defensive patterns
Strategy: validation
Validate before calling
// Reject configs that set both token and tokenSource before loading.
func authNotConflicting(token string, tokenSource *v1.ValueSource) error {
if token != "" && tokenSource != nil {
return fmt.Errorf("set either auth.token or auth.tokenSource, not both")
}
return nil
} Type guard
func hasSingleAuthSource(token string, tokenSource *v1.ValueSource) bool {
return token == "" || tokenSource == nil
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- exec configuration is required when type is 'exec'
- file path cannot be empty
- invalid auth.tokenSource: %v
- invalid auth method, optional values are %v
- exec command cannot be empty
AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15).
Data as JSON: /api/errors/7bd62b25b723710a.
Report an issue: GitHub.