{"record":{"id":"14d4a608b456ea52","repo":"hashicorp/terraform","slug":"unexpected-token-after-valid-json-v","errorCode":null,"errorMessage":"unexpected token after valid JSON: %v","messagePattern":"unexpected token after valid JSON: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/command/jsonformat/structured/change.go","lineNumber":327,"sourceCode":"\tfor key, value := range values {\n\t\tout[key] = unmarshalGeneric(value)\n\t}\n\treturn out\n}\n\nfunc ParseJson(reader io.Reader) (interface{}, error) {\n\tdecoder := json.NewDecoder(reader)\n\tdecoder.UseNumber()\n\n\tvar jv interface{}\n\tif err := decoder.Decode(&jv); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// The JSON decoder should have consumed the entire input stream, so\n\t// we should be at EOF now.\n\tif token, err := decoder.Token(); err != io.EOF {\n\t\treturn nil, fmt.Errorf(\"unexpected token after valid JSON: %v\", token)\n\t}\n\n\treturn jv, nil\n}\n","sourceCodeStart":309,"sourceCodeEnd":332,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/command/jsonformat/structured/change.go#L309-L332","documentation":"Returned by structured.ParseJson (change.go:315-328) when, after successfully decoding one JSON value, the decoder encounters a token that is not EOF — meaning the input has trailing content after a complete JSON document. ParseJson is used to unmarshal before/after/unknown/sensitive fields of plan/state changes, so malformed JSON anywhere in those fields surfaces here.","triggerScenarios":"A Change's Before/After/Unknown/Sensitive raw JSON contains more than one JSON value (e.g. two concatenated objects, or an object followed by stray characters). Most often the input comes from the HCP Terraform redacted endpoint or a corrupted/manually-edited plan or state JSON file fed to the renderer.","commonSituations":"Corrupted plan/state files; HCP Terraform redacted-endpoint returning malformed payloads; tools that concatenate JSON documents incorrectly when post-processing terraform output; truncated writes that left partial JSON after a valid prefix.","solutions":["Validate the plan/state JSON is a single well-formed document: `jq empty plan.json` (jq errors on trailing tokens).","Regenerate the plan/state from terraform rather than consuming a possibly-corrupted file.","If the data came from the redacted endpoint, retry the request or report the malformed payload.","Fix any post-processing pipeline that concatenates or truncates JSON documents."],"exampleFix":"# before\n$ terraform show -json tfplan   # tfplan corrupted with trailing bytes\n# after\n$ terraform plan -out=tfplan\n$ terraform show -json tfplan","handlingStrategy":"validation","validationCode":"// Ensure a raw JSON field is a single complete document before ParseJson.\ndec := json.NewDecoder(bytes.NewReader(raw))\nvar v interface{}\nif err := dec.Decode(&v); err != nil {\n    return fmt.Errorf(\"invalid json: %w\", err)\n}\nif _, err := dec.Token(); err != io.EOF {\n    return fmt.Errorf(\"trailing data after json document\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate plan/state JSON with `jq empty file.json` before consuming it.","Regenerate plans/state from terraform instead of using possibly-corrupted files.","Never concatenate JSON documents; emit one object per stream with proper framing."],"tags":["terraform-jsonformat","json","parse-error","malformed-json"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}