Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Terraform By James Joyner IV · · 8 min read

Terraform Error: 'Error in function call' from jsondecode (invalid character)

Quick answer

Fix Terraform jsondecode errors like 'invalid character ... looking for beginning of value': locate the malformed JSON (trailing commas, single quotes, empty input) and correct it.

  • #terraform
  • #iac
  • #troubleshooting
  • #errors
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Exact Error Message


│ Error: Error in function call

│   on data.tf line 7, in locals:
│    7:   policy = jsondecode(file("${path.module}/policy.json"))

│ Call to function "jsondecode" failed: invalid character '}' looking for
│ beginning of object key string.

Other frequent variants of the same failure:

│ Call to function "jsondecode" failed: invalid character 'e' looking for
│ beginning of value.
│ Call to function "jsondecode" failed: unexpected end of JSON input.

What It Means

jsondecode(string) parses a JSON document into a Terraform value. JSON is strict: keys and strings must use double quotes, no trailing commas are allowed, and comments are forbidden. When the input violates the spec, the Go JSON parser Terraform uses reports the offending character and what it expected next.

“invalid character ’}’ looking for beginning of object key string” almost always means a trailing comma before the closing brace. “invalid character ‘e’” typically means unquoted text (like a bare true/enabled used as a key). “unexpected end of JSON input” means the string was empty or truncated. All of these are input problems fixed before anything is created.

Common Causes

  • A trailing comma after the last element of an object or array.
  • Single quotes instead of double quotes around keys or string values.
  • JavaScript-style // comments or /* */ in the file (JSON has no comments).
  • An empty file or empty string, producing “unexpected end of JSON input”.
  • Feeding already-decoded data (a map/object) back into jsondecode, which expects a string.
  • A shell/CI step that wrote partial output, leaving truncated JSON.

Diagnostic Commands

Validate the JSON with jq, which prints the exact parse location:

jq empty policy.json

Or with Python for a slightly different pointer style:

python3 -c "import json; json.load(open('policy.json'))"

Reproduce the decode with the same input in the Terraform console:

echo 'jsondecode(file("policy.json"))' | terraform console

Run a validate to confirm the resource address and rule out other errors:

terraform validate

Step-by-Step Resolution

  1. Read the character in the message. '}' or ']' “looking for beginning of … key/value” almost always means a trailing comma just before it.

  2. Remove trailing commas and switch any single quotes to double quotes. Valid JSON looks like:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "*"
    }
  ]
}
  1. Strip any comments — JSON does not support them. If you need annotated source, keep comments in HCL and build the JSON with jsonencode instead:
locals {
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = "s3:GetObject"
      Resource = "*"
    }]
  })
}
  1. Guard against empty input so a blank file does not fault the plan with “unexpected end of JSON input”:
locals {
  raw    = file("${path.module}/policy.json")
  policy = try(jsondecode(local.raw), {})
}
  1. Make sure you are passing a string to jsondecode. If the value is already an object, drop the call — you do not decode twice.

  2. Re-test in the console, then validate:

echo 'jsondecode(file("policy.json"))' | terraform console
terraform validate

Prevention

  • Lint JSON in CI with jq empty (or terraform fmt for inline HCL) before Terraform runs.
  • Prefer jsonencode over hand-written JSON strings so Terraform guarantees valid output.
  • Keep policy and config JSON free of comments and trailing commas; enable JSON linting in your editor.
  • Wrap jsondecode in try() when the source might be empty or partially written.
  • When JSON comes from an external process, verify it is complete before decoding (check exit status and length).
  • Error in function call from yamldecode — the YAML equivalent parse failure.
  • Invalid template interpolation value — interpolating a decoded object/list into a string.
  • Unsupported attribute — reading a key the JSON did not define after a successful decode.
  • Call to function "file" failed — the path is wrong, so jsondecode receives nothing.

Frequently Asked Questions

What does “invalid character ’}’” usually mean? A trailing comma before the closing brace or bracket. JSON forbids trailing commas — remove the last comma and re-run.

Can I put comments in the JSON file? No. JSON has no comment syntax. Keep comments in HCL and generate the JSON with jsonencode, or store them out-of-band.

Why does an empty file break the plan? An empty or truncated string yields “unexpected end of JSON input”. Wrap the call in try(jsondecode(local.raw), {}) so a blank file degrades to a default. A Terraform prompt can help you write that fallback.

Should I use jsondecode or jsonencode? Use jsondecode to read external JSON into Terraform, and jsonencode to produce JSON from HCL values — the latter is always valid by construction. For more decoding fixes, see the Terraform guides.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.