Common causes
1. A map or object value missing its brace
A tags = { without its own } steals the brace of the enclosing block. Indentation makes this easy to spot once the file is formatted.
resource "aws_s3_bucket" "logs" {
tags = {
Team = "platform"
}resource "aws_s3_bucket" "logs" {
tags = {
Team = "platform"
}
}2. A block cut short when copying
Copying a resource from documentation or another module often leaves out the last line. Each nested block (lifecycle, ingress, dynamic) needs its own closing brace too.
resource "aws_security_group" "web" {
ingress {
from_port = 443
to_port = 443
}resource "aws_security_group" "web" {
ingress {
from_port = 443
to_port = 443
}
}3. An unterminated string
A missing closing quote makes the string run past the brace, so Terraform never sees the }. Close the quote and the brace reappears.
variable "region" {
default = "eu-west-1
}variable "region" {
default = "eu-west-1"
}4. An unclosed ${ interpolation
Inside a string, ${ opens a template expression that needs its own }. Without it, the rest of the file is read as part of the expression.
locals {
name = "${var.env-app"
}locals {
name = "${var.env}-app"
}Frequently asked questions
How do I find which brace is missing?
Format the file: once braces are unbalanced, the indentation of the closing lines stops matching the openings. terraform fmt refuses invalid files, but PasteKit points at the block that is still open.
What does "Argument or block definition required" mean?
Terraform found something at the top level of a body that is neither name = value nor a block, often a stray closing brace or text left after an edit. It is the mirror image of an unclosed block.
Does this apply to .tfvars and Packer files?
Yes. They use the same HCL syntax, so braces, quotes and interpolations must be balanced in exactly the same way.