fatedier/frp · error

unsupported value source type: %s

Error message

unsupported value source type: %s

What it means

ValueSource.Resolve() hits its default switch branch when Type is neither "file" nor "exec". In practice this branch is nearly unreachable because Resolve() calls Validate() first, which rejects the same condition with a more descriptive message (error 260). Seeing this exact message usually means Validate() was bypassed or the struct was mutated between validation and resolution.

Source

Thrown at pkg/config/v1/value_source.go:85

		return v.Exec.Validate()
	default:
		return fmt.Errorf("unsupported value source type: %s (only 'file' and 'exec' are supported)", v.Type)
	}
}

// Resolve resolves the value from the configured source.
func (v *ValueSource) Resolve(ctx context.Context) (string, error) {
	if err := v.Validate(); err != nil {
		return "", err
	}

	switch v.Type {
	case "file":
		return v.File.Resolve(ctx)
	case "exec":
		return v.Exec.Resolve(ctx)
	default:
		return "", fmt.Errorf("unsupported value source type: %s", v.Type)
	}
}

// Validate validates the FileSource configuration.
func (f *FileSource) Validate() error {
	if f == nil {
		return errors.New("fileSource cannot be nil")
	}

	if f.Path == "" {
		return errors.New("file path cannot be empty")
	}
	return nil
}

// Resolve reads and returns the content from the specified file.
func (f *FileSource) Resolve(_ context.Context) (string, error) {
	if err := f.Validate(); err != nil {

View on GitHub (pinned to 6c8a8d0a97)

Solutions

  1. Fix the Type to "file" or "exec" as with error 260 — this is the same root cause.
  2. If you mutate ValueSource fields, re-run Validate() after mutation and before Resolve().
  3. Avoid sharing a ValueSource across goroutines with writes; construct a fresh one per resolution.

Example fix

// before
vs := &ValueSource{Type: "vault"}
val, err := vs.Resolve(ctx)

// after
vs := &ValueSource{Type: "exec", Exec: &ExecSource{Command: "vault", Args: []string{"kv", "get", "-field=tok", "frp"}}}
if err := vs.Validate(); err != nil { return err }
val, err := vs.Resolve(ctx)
Defensive patterns

Strategy: validation

Validate before calling

if err := vs.Validate(); err != nil {
	return "", fmt.Errorf("value source invalid: %w", err)
}

Prevention

When it happens

Trigger: Calling ValueSource.Resolve(ctx) with an unsupported Type while somehow skipping the upfront Validate() error — e.g. code that ignores the Validate() error inside Resolve, or a ValueSource mutated concurrently after validation.

Common situations: A concurrent goroutine rewrites v.Type between the Validate() call at the top of Resolve and the switch; custom code copies the struct and changes Type without revalidating.

Related errors


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