{"id":"ec49a361348a03a1","repo":"labstack/echo","slug":"options-are-only-supported-for-time-time-got-t","errorCode":null,"errorMessage":"options are only supported for time.Time, got %T","messagePattern":"options are only supported for time\\.Time, got %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"binder_generic.go","lineNumber":410,"sourceCode":"//   - time.Time use echo.TimeOpts or echo.TimeLayout to set time parsing configuration\nfunc ParseValueOr[T any](value string, defaultValue T, opts ...any) (T, error) {\n\tif len(value) == 0 {\n\t\treturn defaultValue, nil\n\t}\n\tvar tmp T\n\tif err := bindValue(value, &tmp, opts...); err != nil {\n\t\tvar zero T\n\t\treturn zero, fmt.Errorf(\"failed to parse value, err: %w\", err)\n\t}\n\treturn tmp, nil\n}\n\nfunc bindValue(value string, dest any, opts ...any) error {\n\t// NOTE: if this function is ever made public the dest should be checked for nil\n\t// values when dealing with interfaces\n\tif len(opts) > 0 {\n\t\tif _, isTime := dest.(*time.Time); !isTime {\n\t\t\treturn fmt.Errorf(\"options are only supported for time.Time, got %T\", dest)\n\t\t}\n\t}\n\n\tswitch d := dest.(type) {\n\tcase *bool:\n\t\tn, err := strconv.ParseBool(value)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t*d = n\n\tcase *float32:\n\t\tn, err := strconv.ParseFloat(value, 32)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\t*d = float32(n)\n\tcase *float64:\n\t\tn, err := strconv.ParseFloat(value, 64)","sourceCodeStart":392,"sourceCodeEnd":428,"githubUrl":"https://github.com/labstack/echo/blob/05489dc1730161df26b72d1ae2a3ba6fb8178fc7/binder_generic.go#L392-L428","documentation":"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.","triggerScenarios":"Calling echo.FormValue[int](c, \"n\", echo.TimeLayout(time.RFC3339)) or ParseValue[float64](\"1.0\", echo.TimeOpts{...}) — passing opts to a non-time generic.","commonSituations":"Copy-pasting opts from a time-binding call into an int/string binding; assuming opts are generic format hints.","solutions":["Drop the opts argument when T is not time.Time","Switch the type parameter to time.Time if you need layout control","For custom formats on other scalar types, implement BindUnmarshaler"],"exampleFix":"// before\nn, err := echo.FormValue[int](c, \"n\", echo.TimeLayout(time.RFC3339))\n// after\nn, err := echo.FormValue[int](c, \"n\")","handlingStrategy":"type-guard","validationCode":"// only pass opts when the target is time.Time\nvar zero T\nif _, ok := any(zero).(time.Time); !ok && len(opts) > 0 {\n    opts = nil\n}","typeGuard":"func acceptsTimeOpts[T any]() bool {\n    var z T\n    _, ok := any(z).(time.Time)\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Pass opts only to time.Time bindings","Encapsulate time bindings in a helper that owns the opts"],"tags":["binding","type-mismatch"],"analyzedSha":"05489dc1730161df26b72d1ae2a3ba6fb8178fc7","analyzedAt":"2026-08-04T21:32:47.783Z","schemaVersion":2}