{"record":{"id":"0019e347a9c1a24b","repo":"hashicorp/terraform","slug":"either-a-string-or-an-integer-is-required","errorCode":null,"errorMessage":"either a string or an integer is required","messagePattern":"either a string or an integer is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/addrs/instance_key.go","lineNumber":48,"sourceCode":"}\n\n// ParseInstanceKey returns the instance key corresponding to the given value,\n// which must be known and non-null.\n//\n// If an unknown or null value is provided then this function will panic. This\n// function is intended to deal with the values that would naturally be found\n// in a hcl.TraverseIndex, which (when parsed from source, at least) can never\n// contain unknown or null values.\nfunc ParseInstanceKey(key cty.Value) (InstanceKey, error) {\n\tswitch key.Type() {\n\tcase cty.String:\n\t\treturn StringKey(key.AsString()), nil\n\tcase cty.Number:\n\t\tvar idx int\n\t\terr := gocty.FromCtyValue(key, &idx)\n\t\treturn IntKey(idx), err\n\tdefault:\n\t\treturn NoKey, fmt.Errorf(\"either a string or an integer is required\")\n\t}\n}\n\n// NoKey represents the absense of an InstanceKey, for the single instance\n// of a configuration object that does not use \"count\" or \"for_each\" at all.\nvar NoKey InstanceKey\n\n// WildcardKey represents the \"unknown\" value of an InstanceKey. This is used\n// within the deferral logic to express absolute module and resource addresses\n// that are not known at the time of planning.\nvar WildcardKey InstanceKey = &wildcardKey{}\n\n// wildcardKey is a special kind of InstanceKey that represents the \"unknown\"\n// value of an InstanceKey. This is used within the deferral logic to express\n// absolute module and resource addresses that are not known at the time of\n// planning.\ntype wildcardKey struct{}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/addrs/instance_key.go#L30-L66","documentation":"Returned by ParseInstanceKey when the cty.Value passed in is neither a String nor a Number — the only two index types Terraform permits for count/for_each instances. The function explicitly panics on null/unknown values (documented), so reaching the default branch means a value of some other concrete type (bool, list, object, etc.) was used as an index.","triggerScenarios":"Returned at internal/addrs/instance_key.go:48 (default switch case). Callers include parse_ref.go:319/542/657, parse_target.go:270, action.go:488, and stacks address parsers (component.go:207, in_stack.go:189, removed.go:361) — all feeding a hcl.TraverseIndex.Key into ParseInstanceKey.","commonSituations":"A resource address literal with a non-string/number index, e.g. `aws_instance.web[true]` or an index expression that evaluates to a list/object. Programmatic address parsing (terraform address -target) with a malformed instance key. A stacks/component iteration using an unsupported key type. HCL produced by tooling that emits an invalid traverse index.","solutions":["Change the index expression to evaluate to a string or integer: `resource[\"name\"]` or `resource[0]`.","If iterating, ensure for_each maps to strings and count to integers; never use a bool/complex value as the key.","When parsing addresses programmatically, validate the index token type before calling ParseInstanceKey.","Audit the generated/templated HCL if the address comes from codegen."],"exampleFix":"// before (bool index -> error)\nresource \"aws_instance\" \"web\" {\n  count = var.enabled ? 1 : 0\n}\n// referencing as aws_instance.web[true] fails\n// after\noutput \"first\" { value = aws_instance.web[0].id }","handlingStrategy":"type-guard","validationCode":"// Only feed String/Number values to ParseInstanceKey.\nfunc isParsableKey(v cty.Value) bool {\n    return v.Type() == cty.String || v.Type() == cty.Number\n}\nif !isParsableKey(idx.Key) {\n    return fmt.Errorf(\"instance index must be string or number\")\n}","typeGuard":"func isValidIndexType(v cty.Value) bool {\n    return v.IsKnown() && !v.IsNull() && (v.Type() == cty.String || v.Type() == cty.Number)\n}","tryCatchPattern":"key, err := addrs.ParseInstanceKey(idx.Key)\nif err != nil {\n    // re-surface as a config/source-range diagnostic so the user sees the location\n    return diags.Append(hclDiagnosticFromError(err))\n}","preventionTips":["Never index resources with bool/list/object values.","Validate traverse-index types before parsing addresses.","Ensure codegen emits only string/number indices."],"tags":["addresses","instance-key","count","for-each","validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}