labstack/echo · error

options are only supported for time.Time, got %T

Error message

options are only supported for time.Time, got %T

What it means

Returned by bindValue (binder_generic.go:408-412) when caller passed parsing options (TimeOpts/TimeLayout) but the destination type is not *time.Time. Options are honoured exclusively inside the *time.Time switch case (binder_generic.go:501-522); every other type rejects them.

Source

Thrown at binder_generic.go:410

//   - time.Time use echo.TimeOpts or echo.TimeLayout to set time parsing configuration
func ParseValueOr[T any](value string, defaultValue T, opts ...any) (T, error) {
	if len(value) == 0 {
		return defaultValue, nil
	}
	var tmp T
	if err := bindValue(value, &tmp, opts...); err != nil {
		var zero T
		return zero, fmt.Errorf("failed to parse value, err: %w", err)
	}
	return tmp, nil
}

func bindValue(value string, dest any, opts ...any) error {
	// NOTE: if this function is ever made public the dest should be checked for nil
	// values when dealing with interfaces
	if len(opts) > 0 {
		if _, isTime := dest.(*time.Time); !isTime {
			return fmt.Errorf("options are only supported for time.Time, got %T", dest)
		}
	}

	switch d := dest.(type) {
	case *bool:
		n, err := strconv.ParseBool(value)
		if err != nil {
			return err
		}
		*d = n
	case *float32:
		n, err := strconv.ParseFloat(value, 32)
		if err != nil {
			return err
		}
		*d = float32(n)
	case *float64:
		n, err := strconv.ParseFloat(value, 64)

View on GitHub (pinned to 05489dc173)

Solutions

  1. Drop the opts argument when T is not time.Time
  2. Switch the type parameter to time.Time if you need layout control
  3. For custom formats on other scalar types, implement BindUnmarshaler

Example fix

// before
n, err := echo.FormValue[int](c, "n", echo.TimeLayout(time.RFC3339))
// after
n, err := echo.FormValue[int](c, "n")
Defensive patterns

Strategy: type-guard

Validate before calling

// only pass opts when the target is time.Time
var zero T
if _, ok := any(zero).(time.Time); !ok && len(opts) > 0 {
    opts = nil
}

Type guard

func acceptsTimeOpts[T any]() bool {
    var z T
    _, ok := any(z).(time.Time)
    return ok
}

Prevention

When it happens

Trigger: Calling echo.FormValue[int](c, "n", echo.TimeLayout(time.RFC3339)) or ParseValue[float64]("1.0", echo.TimeOpts{...}) — passing opts to a non-time generic.

Common situations: Copy-pasting opts from a time-binding call into an int/string binding; assuming opts are generic format hints.

Related errors


AI-assisted analysis of labstack/echo@05489dc173 (2026-08-04). Data as JSON: /data/errors/ec49a361348a03a1.json. Report an issue: GitHub.