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 current

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Dynamically build the type argument list based on TypeParams().Len()
  2. Count type parameters before constructing type arguments to ensure they match
  3. Add a unit test that verifies Instantiate succeeds for each generic type you process
  4. 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

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


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/d235573263ae574e. Report an issue: GitHub.