hashicorp/terraform · critical
NewInstanceInfo cannot convert module instance with key
Error message
NewInstanceInfo cannot convert module instance with key
What it means
Panics by design in NewInstanceInfo (resource.go:62). The legacy InstanceInfo type cannot represent module instances created with count/for_each; if any module path step has a non-NoKey instance key, it panics. The docstring explicitly warns this path must be resolved before module count/for_each is supported.
Source
Thrown at internal/legacy/terraform/resource.go:62
//
// InstanceInfo is a legacy type, and uses of it should be gradually replaced
// by direct use of addrs.AbsResource or addrs.AbsResourceInstance as
// appropriate.
//
// The legacy InstanceInfo type cannot represent module instances with instance
// keys, so this function will panic if given such a path. Uses of this type
// should all be removed or replaced before implementing "count" and "for_each"
// arguments on modules in order to avoid such panics.
//
// This legacy type also cannot represent resource instances with string
// instance keys. It will panic if the given key is not either NoKey or an
// IntKey.
func NewInstanceInfo(addr addrs.AbsResourceInstance) *InstanceInfo {
// We need an old-style []string module path for InstanceInfo.
path := make([]string, len(addr.Module))
for i, step := range addr.Module {
if step.InstanceKey != addrs.NoKey {
panic("NewInstanceInfo cannot convert module instance with key")
}
path[i] = step.Name
}
// This is a funny old meaning of "id" that is no longer current. It should
// not be used for anything users might see. Note that it does not include
// a representation of the resource mode, and so it's impossible to
// determine from an InstanceInfo alone whether it is a managed or data
// resource that is being referred to.
id := fmt.Sprintf("%s.%s", addr.Resource.Resource.Type, addr.Resource.Resource.Name)
if addr.Resource.Resource.Mode == addrs.DataResourceMode {
id = "data." + id
}
if addr.Resource.Key != addrs.NoKey {
switch k := addr.Resource.Key.(type) {
case addrs.IntKey:
id = id + fmt.Sprintf(".%d", int(k))
default:View on GitHub (pinned to c9def3e214)
Solutions
- Upgrade the provider to a build against a newer SDK that no longer routes through legacy InstanceInfo.
- Avoid count/for_each on the module blocks that exercise the affected legacy provider path.
- Restructure: move the resource out of the counted module, or replicate the module manually.
Example fix
// before
module "svc" { count = var.n, source = "./svc" }
// after
module "svc_a" { source = "./svc" }
module "svc_b" { source = "./svc" } Defensive patterns
Strategy: validation
Validate before calling
func noModuleInstanceKeys(addr addrs.AbsResourceInstance) error {
for _, step := range addr.Module {
if step.InstanceKey != addrs.NoKey {
return fmt.Errorf("module %s has instance key; legacy InstanceInfo unsupported", step)
}
}
return nil
} Prevention
- Avoid count/for_each on modules that exercise legacy provider paths.
- Upgrade providers to newer SDK builds.
- Prefer modern addrs types over legacy InstanceInfo.
When it happens
Trigger: A provider using the legacy helper/schema ResourceData path is exercised against a module instance created with `count` or `for_each` on a module block, routing through NewInstanceInfo.
Common situations: Older SDK-based providers run under Terraform configurations that apply count/for_each to module blocks; SDK version lag.
Related errors
- NewInstanceInfo cannot convert resource instance with %T ins
- NewResourceConfigShimmed given %#v; an object type is requir
- this working directory uses legacy remote state and so must
- found unrecognized resource mode:
- found unrecognized resource mode:
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/1a67f6a8564ce3aa.
Report an issue: GitHub.