hashicorp/terraform · critical
NewInstanceInfo cannot convert resource instance with %T ins
Error message
NewInstanceInfo cannot convert resource instance with %T instance key
What it means
Panics in NewInstanceInfo (resource.go:81). The legacy type can only represent resource instances with NoKey or IntKey (count); a string key produced by for_each hits the default branch and panics.
Source
Thrown at internal/legacy/terraform/resource.go:81
}
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:
panic(fmt.Sprintf("NewInstanceInfo cannot convert resource instance with %T instance key", addr.Resource.Key))
}
}
return &InstanceInfo{
Id: id,
ModulePath: path,
Type: addr.Resource.Resource.Type,
}
}
// ResourceConfig is a legacy type that was formerly used to represent
// interpolatable configuration blocks. It is now only used to shim to old
// APIs that still use this type, via NewResourceConfigShimmed.
type ResourceConfig struct {
ComputedKeys []string
Raw map[string]interface{}
Config map[string]interface{}
}View on GitHub (pinned to c9def3e214)
Solutions
- Upgrade the provider/SDK so the resource no longer goes through legacy InstanceInfo.
- Replace for_each with count (integer keys) on the affected resource.
- Reorganize the config so the resource is not in a for_each block.
Example fix
// before
resource "x" "y" { for_each = toset(["a","b"]) }
// after
resource "x" "y" { count = 2 } Defensive patterns
Strategy: validation
Validate before calling
func resourceKeyLegacyOk(addr addrs.AbsResourceInstance) error {
switch k := addr.Resource.Key.(type) {
case addrs.NoKey, addrs.IntKey: return nil
default: return fmt.Errorf("resource instance key %T unsupported by legacy InstanceInfo", k)
}
} Type guard
func isLegacyCompatibleKey(k addrs.InstanceKey) bool {
switch k.(type) {
case addrs.NoKey, addrs.IntKey: return true
}
return false
} Prevention
- Use count (IntKey) instead of for_each (string keys) where legacy paths are involved.
- Upgrade provider/SDK.
- Reorganize resources out of for_each blocks.
When it happens
Trigger: A resource created with `for_each` (string keys) is routed through the legacy InstanceInfo path.
Common situations: An older provider/SDK used with for_each on a managed resource that exercises legacy code paths.
Related errors
- NewInstanceInfo cannot convert module instance with key
- NewResourceConfigShimmed given %#v; an object type is requir
- either a string or an integer is required
- Error: unsupported resource %s
- this working directory uses legacy remote state and so must
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/8612e4d54d603bfb.
Report an issue: GitHub.