golang/go · error
cannot instantiate %s: got %d type arguments but have %d typ
Error message
cannot instantiate %s: got %d type arguments but have %d type parameters
What it means
When instantiating a generic type with validate=true, Instantiate checks that the number of type arguments matches the number of declared type parameters. This error fires when the counts differ, including both numbers in the message for diagnosis. The type is confirmed generic (has type parameters) but the caller supplied the wrong number of arguments.
Source
Thrown at src/cmd/compile/internal/types2/instantiate.go:69
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].
//
// If expanding is non-nil, it is the Named instance type currently being
// expanded. If ctxt is non-nil, it is the context associated with the currentView on GitHub (pinned to b6b368adc5)
Solutions
- Dynamically build the type argument list based on TypeParams().Len()
- Count type parameters before constructing type arguments to ensure they match
- Add a unit test that verifies Instantiate succeeds for each generic type you process
- When iterating over types, skip or log types where TypeParams().Len() != len(targs)
Example fix
// before
inst, err := types.Instantiate(ctxt, genericType, []types.Type{intType}, true)
// after
n := genericType.TypeParams().Len()
targs := make([]types.Type, n)
for i := 0; i < n; i++ {
targs[i] = resolveTypeArg(genericType.TypeParams().At(i))
}
inst, err := types.Instantiate(ctxt, genericType, targs, true) Defensive patterns
Strategy: type-guard
Validate before calling
// Build type arguments dynamically based on type parameter count
func instantiateWithCorrectArity(ctxt *types.Context, t types.Type) (types.Type, error) {
named, ok := t.(*types.Named)
if !ok {
return t, nil
}
tparams := named.TypeParams()
if tparams.Len() == 0 {
return t, nil
}
targs := make([]types.Type, tparams.Len())
for i := 0; i < tparams.Len(); i++ {
// Resolve type argument for each parameter
targs[i] = resolveTypeArg(tparams.At(i))
}
return types.Instantiate(ctxt, t, targs, true)
} Type guard
// Check that type argument count matches type parameter count
func arityMatches(t types.Type, targs []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 len(targs) == 0
}
return tparams != nil && tparams.Len() == len(targs)
} Try / catch
// Handle instantiation errors gracefully
inst, err := types.Instantiate(ctxt, t, targs, true)
if err != nil {
if strings.Contains(err.Error(), "type arguments but have") {
// arity mismatch — log and skip this type
log.Printf("skipping %v: %v", t, err)
return nil
}
return fmt.Errorf("instantiation failed: %w", err)
} Prevention
- Always derive the number of type arguments from TypeParams().Len(), never hard-code it
- When a generic type's parameter count changes, use compiler errors to find all call sites
- Add unit tests for each generic type that verify Instantiate succeeds with the correct arity
- In type processing loops, skip types where TypeParams().Len() != len(targs)
When it happens
Trigger: Calling types.Instantiate(ctxt, genericType, wrongNumberOfArgs, true). For example, a type with 2 type parameters instantiated with 1 or 3 arguments: types.Instantiate(ctxt, mapType, []types.Type{intType}, true) for a Map[K, V].
Common situations: Mistakes in generic instantiation code where the argument count doesn't match. Changes to a generic type's parameter count (adding or removing a type parameter) without updating all instantiation call sites. Hard-coded type argument lists that go stale after refactoring.
Related errors
- cannot instantiate non-generic %s: has no type parameters
- 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/d235573263ae574e.
Report an issue: GitHub.