oauth2-proxy/oauth2-proxy · error

unknown type for destination: %T

Error message

unknown type for destination: %T

What it means

CoerceClaim returns this error when the destination pointer is of a type it does not support. Only *string, *[]string, and *bool destinations are handled; anything else (e.g. *int, map[string]any, non-pointer) falls into the default case. The %T verb names the offending destination type.

Source

Thrown at pkg/util/util.go:218

// interface.
func CoerceClaim(value, dst any) error {
	switch d := dst.(type) {
	case *string:
		str, err := toString(value)
		if err != nil {
			return fmt.Errorf("could not convert value to string: %v", err)
		}
		*d = str
	case *[]string:
		strSlice, err := toStringSlice(value)
		if err != nil {
			return fmt.Errorf("could not convert value to string slice: %v", err)
		}
		*d = strSlice
	case *bool:
		*d = cast.ToBool(value)
	default:
		return fmt.Errorf("unknown type for destination: %T", dst)
	}
	return nil
}

// toStringSlice converts an interface (either a slice or single value) into
// a slice of strings.
func toStringSlice(value any) ([]string, error) {
	var sliceValues []any
	switch v := value.(type) {
	case []any:
		sliceValues = v
	default:
		sliceValues = []any{v}
	}

	out := []string{}
	for _, v := range sliceValues {
		str, err := toString(v)

View on GitHub (pinned to 33c2eb92de)

Solutions

  1. Change the destination to one of the supported types (*string, *[]string, *bool)
  2. Convert manually to a supported type first (e.g. coerce to string then strconv.Atoi)
  3. Update the library if you need additional destination types, or add a case in CoerceClaim for your type
  4. Ensure you pass a pointer, not a value

Example fix

// before
var count int
err := util.CoerceClaim(claims["access_count"], &count)
// after
var countStr string
err := util.CoerceClaim(claims["access_count"], &countStr)
count, _ = strconv.Atoi(countStr)
Defensive patterns

Strategy: type-guard

Validate before calling

switch dst.(type) { case *string, *[]string, *bool: /* supported */ default: /* unsupported */ }

Type guard

func supportedDst(dst any) bool {
    switch dst.(type) {
    case *string, *[]string, *bool:
        return true
    }
    return false
}

Try / catch

if !supportedDst(dst) {
    return fmt.Errorf("unsupported destination %T", dst)
}

Prevention

When it happens

Trigger: getAdditionalClaim, GetClaimInto, or caller code passes a destination other than *string, *[]string, or *bool to CoerceClaim, hitting the default branch.

Common situations: Trying to coerce a numeric claim into *int or *float64; passing a non-pointer value; config code written against a newer CoerceClaim signature with extra supported types.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of oauth2-proxy/oauth2-proxy@33c2eb92de (2026-09-06). Data as JSON: /api/errors/6eb55b14a0e1158a. Report an issue: GitHub.