{"record":{"id":"bff2a95a9a0f7079","repo":"hashicorp/terraform","slug":"argument-must-be-a-string-a-collection-type-or-a","errorCode":null,"errorMessage":"argument must be a string, a collection type, or a structural type","messagePattern":"argument must be a string, a collection type, or a structural type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lang/funcs/collection.go","lineNumber":35,"sourceCode":")\n\nvar LengthFunc = function.New(&function.Spec{\n\tParams: []function.Parameter{\n\t\t{\n\t\t\tName:             \"value\",\n\t\t\tType:             cty.DynamicPseudoType,\n\t\t\tAllowDynamicType: true,\n\t\t\tAllowUnknown:     true,\n\t\t\tAllowMarked:      true,\n\t\t},\n\t},\n\tType: func(args []cty.Value) (cty.Type, error) {\n\t\tcollTy := args[0].Type()\n\t\tswitch {\n\t\tcase collTy == cty.String || collTy.IsTupleType() || collTy.IsObjectType() || collTy.IsListType() || collTy.IsMapType() || collTy.IsSetType() || collTy == cty.DynamicPseudoType:\n\t\t\treturn cty.Number, nil\n\t\tdefault:\n\t\t\treturn cty.Number, errors.New(\"argument must be a string, a collection type, or a structural type\")\n\t\t}\n\t},\n\tRefineResult: refineNotNull,\n\tImpl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {\n\t\tcoll := args[0]\n\t\tcollTy := args[0].Type()\n\t\tmarks := coll.Marks()\n\n\t\tswitch {\n\t\tcase collTy == cty.DynamicPseudoType:\n\t\t\treturn cty.UnknownVal(cty.Number).WithMarks(marks), nil\n\t\tcase collTy.IsTupleType():\n\t\t\tl := len(collTy.TupleElementTypes())\n\t\t\treturn cty.NumberIntVal(int64(l)).WithMarks(marks), nil\n\t\tcase collTy.IsObjectType():\n\t\t\tl := len(collTy.AttributeTypes())\n\t\t\treturn cty.NumberIntVal(int64(l)).WithMarks(marks), nil\n\t\tcase collTy == cty.String:","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/lang/funcs/collection.go#L17-L53","documentation":"Thrown by the `length()` HCL function (LengthFunc) when its single argument's cty type is not one of string, tuple, object, list, map, set, or dynamic. The Type callback enumerates the accepted types and rejects everything else (numbers, booleans) at type-check time, before the implementation runs. Numbers and booleans have no meaningful length, so they are rejected outright.","triggerScenarios":"Calling `length()` in an HCL/Terraform config with a number or boolean value, e.g. `length(var.replicas)` where var.replicas is `number`. The Type func switch falls to the default branch and returns this error.","commonSituations":"Mis-naming a variable so a scalar (count, bool flag, port number) is passed instead of the intended list/map. Refactoring a variable from list(number) to number and forgetting to update its `length()` call. Passing a single string char count where `strlen` semantics differ.","solutions":["Pass a value of an accepted type: string, list, set, map, tuple, or object. Inspect the variable declaration and confirm it is a collection.","If you meant the magnitude of a number, numbers are used directly — remove the length() call.","If the value is computed/unknown, ensure it is at least typed as a collection; dynamic values are allowed but a definitely-number type is not."],"exampleFix":"// before\noutput \"n\" { value = length(var.replica_count) }   # var.replica_count is number\n\n// after\noutput \"n\" { value = length(var.replica_names) }    # var.replica_names is list(string)","handlingStrategy":"validation","validationCode":"# HCL: confirm the variable is a collection before calling length()\nlocals {\n  ok = can([for v in var.input : v])  # true only for list/set/tuple\n  n  = local.ok ? length(var.input) : 0\n}","typeGuard":"# HCL guard using try() to fall back on non-collections\nlocals { n = try(length(var.input), 0) }","tryCatchPattern":null,"preventionTips":["Declare variables with explicit collection types (list(...), map(...), set(...)) so misuse is caught at validation.","Use `terraform validate` in CI to surface length() type errors before apply.","Run `terraform fmt` + editor type hints to catch scalar-vs-collection mix-ups early."],"tags":["terraform","hcl","collection-functions","length","type-check"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}