golang/go · error
cannot instantiate non-generic %s: has no type parameters
Error message
cannot instantiate non-generic %s: has no type parameters
What it means
The Instantiate function (exported as go/types.Instantiate) creates a concrete type from a generic type by substituting type arguments. When called with validate=true on a type whose TypeParams().list() is empty, this error is returned. The type was recognized as a genericType (Named, Alias, or Signature) but has zero declared type parameters.
Source
Thrown at src/cmd/compile/internal/types2/instantiate.go:66
// for *Signature types, Instantiate will panic immediately if the type argument
// count is incorrect; for *Named types, a panic may occur later inside the
// *Named API.
func Instantiate(ctxt *Context, orig Type, targs []Type, validate bool) (Type, error) {
if ctxt == nil {
ctxt = NewContext()
}
orig_, ok := orig.(genericType) // signature of Instantiate must not change for backward-compatibility
if !ok {
panic(sprintf(nil, false, "cannot instantiate non-generic %s: expected *Named, *Alias, or *Signature", orig))
}
if len(targs) == 0 {
panic(sprintf(nil, false, "cannot instantiate %s: empty type argument list", orig))
}
if validate {
tparams := orig_.TypeParams().list()
if len(tparams) == 0 {
return nil, fmt.Errorf("cannot instantiate non-generic %s: has no type parameters", orig)
}
if len(targs) != len(tparams) {
return nil, fmt.Errorf("cannot instantiate %s: got %d type arguments but have %d type parameters", orig, len(targs), len(tparams))
}
if i, err := (*Checker)(nil).verify(nopos, tparams, targs, ctxt); err != nil {
return nil, &ArgumentError{i, err}
}
}
inst := (*Checker)(nil).instance(nopos, orig_, targs, nil, ctxt)
return inst, nil
}
// instance instantiates the given original (generic) function or type with the
// provided type arguments and returns the resulting instance. If an identical
// instance exists already in the given contexts, it returns that instance,
// otherwise it creates a new one. If there is an error (such as wrong number
// of type arguments), the result is Typ[Invalid].View on GitHub (pinned to b6b368adc5)
Solutions
- Check TypeParams().Len() > 0 before calling Instantiate
- Only call Instantiate on types you have confirmed are generic
- Pass validate=false if you do not need validation, but note that panics may occur later for *Named types with wrong argument counts
- Cache genericness checks to avoid repeated TypeParams() calls in hot paths
Example fix
// before
inst, err := types.Instantiate(ctxt, someType, targs, true)
// after
if someType.TypeParams().Len() == 0 {
return someType // not generic, no instantiation needed
}
inst, err := types.Instantiate(ctxt, someType, targs, true) Defensive patterns
Strategy: type-guard
Validate before calling
// Check if a type is generic before calling Instantiate
import (
"go/types"
)
func safeInstantiate(ctxt *types.Context, t types.Type, targs []types.Type) (types.Type, error) {
// Get type parameters from Named, Alias, or Signature
var tparams *types.TypeParamList
switch t := t.(type) {
case *types.Named:
tparams = t.TypeParams()
case *types.Alias:
tparams = t.TypeParams()
case *types.Signature:
tparams = t.TypeParams()
default:
return t, nil // not instantiable, return as-is
}
if tparams == nil || tparams.Len() == 0 {
return t, nil // not generic, no instantiation needed
}
return types.Instantiate(ctxt, t, targs, true)
} Type guard
// Type guard: returns true if the type has type parameters (is generic)
func isGeneric(t types.Type) bool {
var tparams *types.TypeParamList
switch t := t.(type) {
case *types.Named:
tparams = t.TypeParams()
case *types.Alias:
tparams = t.TypeParams()
case *types.Signature:
tparams = t.TypeParams()
default:
return false
}
return tparams != nil && tparams.Len() > 0
} Prevention
- Always check TypeParams().Len() > 0 before calling types.Instantiate with validate=true
- Use a wrapper function (safeInstantiate) that handles the non-generic case gracefully
- In dynamic type processing code, filter out non-generic types before the instantiation loop
- Write unit tests covering both generic and non-generic types in instantiation code
When it happens
Trigger: Calling types.Instantiate(ctxt, nonGenericType, typeArgs, true) where the original type has no type parameters. For example, instantiating a plain *types.Named for a struct without type parameters, or a *types.Signature for a non-generic function.
Common situations: Dynamic type processing code (e.g., in code generators, serializers, or ORMs) that calls Instantiate on all types without checking if they are generic. Stale type information after refactoring a type from generic to non-generic. Reflection-based tools that enumerate and instantiate types programmatically.
Related errors
- cannot instantiate %s: got %d type arguments but have %d typ
- empty string
- invalid character %#U
- Config.Importer not installed
- Config.Importer.ImportFrom(%s, %s, 0) returned nil but no er
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/26b8b9d22190e6df.
Report an issue: GitHub.