{"record":{"id":"99bab479cd0af7b9","repo":"opentofu/opentofu","slug":"empty-value","errorCode":null,"errorMessage":"empty value","messagePattern":"empty value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"info","filePath":"internal/genconfig/generate_config.go","lineNumber":640,"sourceCode":"\ttokens, err := wrapAsJSONEncodeFunctionCall(v)\n\tif err != nil {\n\t\treturn hclwrite.TokensForValue(v)\n\t}\n\treturn tokens\n}\n\nfunc wrapAsJSONEncodeFunctionCall(v cty.Value) (hclwrite.Tokens, error) {\n\tif v.IsNull() || v.Type() != cty.String || !v.IsKnown() {\n\t\treturn nil, errors.New(\"value cannot be treated as JSON string\")\n\t}\n\n\t// Don't let marked value to be passed into functions like AsString()\n\t// to prevent panics.\n\tv, _ = v.Unmark()\n\n\ts := []byte(strings.TrimSpace(v.AsString()))\n\tif len(s) == 0 {\n\t\treturn nil, errors.New(\"empty value\")\n\t}\n\n\tif s[0] != '{' && s[0] != '[' {\n\t\treturn nil, errors.New(\"value is not a JSON object, nor a JSON array\")\n\t}\n\n\tt, err := json.ImpliedType(s)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot define implied cty type (possibly not a JSON string): %w\", err)\n\t}\n\n\tv, err = json.Unmarshal(s, t)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot unmarshal using implied type (possible not a JSON string): %w\", err)\n\t}\n\n\ttokens := hclwrite.TokensForFunctionCall(\"jsonencode\", hclwrite.TokensForValue(v))\n","sourceCodeStart":622,"sourceCodeEnd":658,"githubUrl":"https://github.com/opentofu/opentofu/blob/3561785c48c1ce615e7c50261bd351f26053efa2/internal/genconfig/generate_config.go#L622-L658","documentation":"Internal guard in genconfig's JSON-encode heuristic: the value is a known string but trims to zero length, so it cannot be JSON and is not wrapped in jsonencode(). The caller catches this and emits the empty string as plain HCL, making the error invisible in normal tofu usage.","triggerScenarios":"A known, non-null cty string value consisting solely of whitespace reaching wrapAsJSONEncodeFunctionCall. Only surfaced when the function is called directly rather than via tryWrapAsJsonEncodeFunctionCall.","commonSituations":"Extending or testing the generated-config feature; empty-string attributes in imported resources are simply emitted as \"\" with no jsonencode wrapper.","solutions":["No action needed; fallback behavior is correct for empty strings","When calling directly, pre-check strings.TrimSpace(s) != \"\" to avoid the sentinel error"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"v, _ = v.Unmark()\nif strings.TrimSpace(v.AsString()) == \"\" {\n    return hclwrite.TokensForValue(v) // skip jsonencode heuristic\n}","typeGuard":"func isJSONEncodeCandidate(v cty.Value) bool {\n    if v.IsNull() || !v.IsKnown() || !v.Type().Equals(cty.String) {\n        return false\n    }\n    v, _ = v.Unmark()\n    s := strings.TrimSpace(v.AsString())\n    return len(s) > 0 && (s[0] == '{' || s[0] == '[')\n}","tryCatchPattern":null,"preventionTips":["Pre-trim strings before invoking the heuristic so empty values short-circuit cleanly","Remember empty strings are intentionally emitted as plain HCL, never jsonencode-wrapped"],"tags":["genconfig","internal","control-flow","json"],"backgroundTag":null,"analyzedSha":"3561785c48c1ce615e7c50261bd351f26053efa2","analyzedAt":"2026-08-15T23:27:16.226Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}