hashicorp/terraform · critical
NewResourceConfigShimmed given %#v; an object type is requir
Error message
NewResourceConfigShimmed given %#v; an object type is required
What it means
Panics in NewResourceConfigShimmed (resource.go:139). It wraps a cty.Value into a legacy ResourceConfig and requires val.Type().IsObjectType(); passing a non-object value (primitive, list, map, tuple) panics. The docstring states it will panic if the value is not an object type.
Source
Thrown at internal/legacy/terraform/resource.go:139
Config: cfg,
ComputedKeys: newResourceConfigShimmedComputedKeys(v, ""),
}
}
// NewResourceConfigShimmed wraps a cty.Value of object type in a legacy
// ResourceConfig object, so that it can be passed to older APIs that expect
// this wrapping.
//
// The returned ResourceConfig is already interpolated and cannot be
// re-interpolated. It is, therefore, useful only to functions that expect
// an already-populated ResourceConfig which they then treat as read-only.
//
// If the given value is not of an object type that conforms to the given
// schema then this function will panic.
func NewResourceConfigShimmed(val cty.Value, schema *configschema.Block) *ResourceConfig {
if !val.Type().IsObjectType() {
panic(fmt.Errorf("NewResourceConfigShimmed given %#v; an object type is required", val.Type()))
}
ret := &ResourceConfig{}
legacyVal := hcl2shim.ConfigValueFromHCL2Block(val, schema)
if legacyVal != nil {
ret.Config = legacyVal
// Now we need to walk through our structure and find any unknown values,
// producing the separate list ComputedKeys to represent these. We use the
// schema here so that we can preserve the expected invariant
// that an attribute is always either wholly known or wholly unknown, while
// a child block can be partially unknown.
ret.ComputedKeys = newResourceConfigShimmedComputedKeys(val, "")
} else {
ret.Config = make(map[string]interface{})
}
ret.Raw = ret.Config
View on GitHub (pinned to c9def3e214)
Solutions
- Pass a cty.Value of object type built to conform to the schema block (use cty.ObjectVal or configschema-derived types).
- Check val.Type().IsObjectType() before calling, and wrap/convert when needed.
- Use hcl2shim.ConfigValueFromHCL2Block to produce the correct object shape.
Example fix
// before
cfg := NewResourceConfigShimmed(cty.StringVal("hi"), schema)
// after
cfg := NewResourceConfigShimmed(cty.ObjectVal(map[string]cty.Value{"name": cty.StringVal("hi")}), schema) Defensive patterns
Strategy: type-guard
Validate before calling
func shimConfigSafe(val cty.Value, schema *configschema.Block) (*terraform.ResourceConfig, error) {
if !val.Type().IsObjectType() {
return nil, fmt.Errorf("expected object type, got %s", val.Type().FriendlyName())
}
return terraform.NewResourceConfigShimmed(val, schema), nil
} Type guard
func isCtyObject(v cty.Value) bool { return v.Type().IsObjectType() } Prevention
- Always pass object-typed cty values to NewResourceConfigShimmed.
- Build values with cty.ObjectVal or configschema helpers.
- Validate IsObjectType at call sites that may receive primitives.
When it happens
Trigger: Calling NewResourceConfigShimmed with a cty.Value that is not an object — e.g. passing a single attribute value (cty.StringVal) or a list/tuple where a block-level object is expected.
Common situations: Provider/plugin integration code shimming cty values incorrectly, or passing a nested attribute value instead of the full block object.
Related errors
- NewInstanceInfo cannot convert module instance with key
- NewInstanceInfo cannot convert resource instance with %T ins
- Unsupported path step %#v (%t)
- this working directory uses legacy remote state and so must
- invalid collection length: %s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/5f0e08121113dcc9.
Report an issue: GitHub.