fatedier/frp · error

invalid auth.oidc.tokenSource: %v

Error message

invalid auth.oidc.tokenSource: %v

What it means

The auth.oidc.tokenSource block itself failed its own Validate() call, and this wrapper reports the underlying cause. Typical sub-causes are an empty command/exec args for type "exec" or an unsupported tokenSource type. The %v in the message carries the original error text.

Source

Thrown at pkg/config/v1/validation/client.go:138

func (v *ConfigValidator) validateOIDCConfig(c *v1.AuthOIDCClientConfig) error {
	if c.TokenSource == nil {
		return nil
	}
	var errs error
	// Validate oidc.tokenSource mutual exclusivity with other fields of oidc
	if c.ClientID != "" || c.ClientSecret != "" || c.Audience != "" ||
		c.Scope != "" || c.TokenEndpointURL != "" || len(c.AdditionalEndpointParams) > 0 ||
		c.TrustedCaFile != "" || c.InsecureSkipVerify || c.ProxyURL != "" {
		errs = AppendError(errs, fmt.Errorf("cannot specify both auth.oidc.tokenSource and any other field of auth.oidc"))
	}
	if c.TokenSource.Type == "exec" {
		if err := v.ValidateUnsafeFeature(security.TokenSourceExec); err != nil {
			errs = AppendError(errs, err)
		}
	}
	if err := c.TokenSource.Validate(); err != nil {
		errs = AppendError(errs, fmt.Errorf("invalid auth.oidc.tokenSource: %v", err))
	}
	return errs
}

func validateTransportConfig(c *v1.ClientTransportConfig) (Warning, error) {
	var (
		warnings Warning
		errs     error
	)

	if c.HeartbeatTimeout > 0 && c.HeartbeatInterval > 0 {
		if c.HeartbeatTimeout < c.HeartbeatInterval {
			errs = AppendError(errs, fmt.Errorf("invalid transport.heartbeatTimeout, heartbeat timeout should not less than heartbeat interval"))
		}
	}

	if !lo.FromPtr(c.TLS.Enable) {
		checkTLSConfig := func(name string, value string) Warning {

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Read the inner %v error — it names the exact invalid field
  2. For type = "exec", ensure command is a non-empty executable path and args are well-formed
  3. Ensure tokenSource.type matches a supported value ("exec") for your frp version
  4. Verify featureGates/unsafeFeatures allows TokenSourceExec if you also see gate errors

Example fix

# before
[auth.oidc.tokenSource]
type = "exec"
# command missing

# after
[auth.oidc.tokenSource]
type = "exec"
command = "/usr/local/bin/oidc-helper"
args = ["--audience", "frp"]
Defensive patterns

Strategy: validation

Validate before calling

if cfg.Auth.OIDC.TokenSource != nil {
    if err := cfg.Auth.OIDC.TokenSource.Validate(); err != nil {
        // fix tokenSource fields before full validation
    }
}

Try / catch

if err := validation.ValidateAllClientConfig(cc, proxies, visitors, uf); err != nil {
    if idx := strings.Index(err.Error(), "invalid auth.oidc.tokenSource:"); idx >= 0 {
        inner := strings.TrimSpace(err.Error()[idx+len("invalid auth.oidc.tokenSource:"):])
        // branch on inner ("command is empty" etc.)
    }
}

Prevention

When it happens

Trigger: auth.oidc.tokenSource.type = "exec" with command missing/empty, wrong tokenSource type string, or invalid fields per v1.AuthOIDCTokenSource.Validate(). Also fires only after the exec gate check (ValidateUnsafeFeature for TokenSourceExec) passed.

Common situations: Writing a tokenSource block from memory and omitting 'command'; using a type value not implemented by this frp build; exec plugin path that is whitespace-only.

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/fac0855b6d36ffb6. Report an issue: GitHub.