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

Terraform Error Guide: 'Unsupported argument' (an argument is not expected here)

Fix Terraform's 'Unsupported argument' error: correct typo'd names, match provider versions, separate nested blocks from attributes, and pass module inputs right.

  • #terraform
  • #troubleshooting
  • #errors
  • #configuration

Exact Error Message

Error: Unsupported argument

  on main.tf line 14, in resource "aws_instance" "web":
  14:   instance_typ = "t3.micro"

An argument named "instance_typ" is not expected here.

A variant points at an argument that exists on the resource but in a different form or provider version:

Error: Unsupported argument

  on s3.tf line 9, in resource "aws_s3_bucket" "logs":
   9:   acl = "private"

An argument named "acl" is not expected here.

What the Error Means

Terraform validates every argument you set against the schema published by the provider for that specific resource (or by a module for its input variables). Unsupported argument means the name you used is not in that schema. Terraform is strict: it will not silently ignore an unknown key, because a typo’d argument almost always means the value you intended to set is being dropped.

The schema is tied to a provider version. AWS provider 4.x split aws_s3_bucket into many sub-resources, so acl, versioning, and lifecycle_rule became separate resources or moved into aws_s3_bucket_acl. Code that validated under 3.x fails under 4.x with this exact error even though nothing in your .tf changed.

Common Causes

  • Typo in the argument nameinstance_typ instead of instance_type, tag instead of tags.
  • Provider version mismatch — the argument was renamed, removed, or split out in a major provider bump (the AWS 3.x to 4.x S3 split is the classic case).
  • Attribute that belongs in a nested block — you set cidr_block = ... at the top level of a resource that expects it inside an ingress { } block.
  • A block written as an attribute — using ebs_block_device = { ... } with = when the schema defines ebs_block_device { ... } as a repeatable block.
  • Module input vs resource argument confusion — passing a resource argument name to a module call, or vice versa, when the module only declares specific variable blocks.
  • Deprecated argument removed — an argument that was deprecated for a release and then deleted in the next one.

How to Reproduce the Error

Create a resource with an argument that does not exist on the current provider version:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

resource "aws_instance" "web" {
  ami           = "ami-0abcd1234ef567890"
  instance_typ  = "t3.micro"   # typo: should be instance_type
}
terraform init
terraform validate
Error: Unsupported argument

  on main.tf line 12, in resource "aws_instance" "web":
  12:   instance_typ  = "t3.micro"

An argument named "instance_typ" is not expected here.

Diagnostic Commands

Validate without touching state or the network — this catches schema errors fast:

terraform validate

Confirm exactly which provider version is locked, since the schema depends on it:

terraform providers
terraform version
grep -A3 required_providers *.tf

Dump the live schema for the resource and grep for the argument you tried to use. If it does not appear, the name is wrong for this version:

terraform providers schema -json | \
  jq '.provider_schemas[].resource_schemas["aws_s3_bucket"].block.attributes | keys'

Inspect whether the name is a nested block rather than a top-level attribute:

terraform providers schema -json | \
  jq '.provider_schemas[].resource_schemas["aws_instance"].block.block_types | keys'

Step-by-Step Resolution

1. Read the line the error points at. Terraform gives you the file, line, and argument name. Open the provider documentation for that resource at your pinned version (the registry has a version selector) and compare the spelling.

2. Fix obvious typos.

resource "aws_instance" "web" {
  ami           = "ami-0abcd1234ef567890"
  instance_type = "t3.micro"   # corrected
}

3. If the spelling is correct, check the provider version. The AWS 4.x S3 refactor is the most common surprise. Move the argument to its dedicated resource:

# Old (AWS provider 3.x) — fails on 4.x/5.x
resource "aws_s3_bucket" "logs" {
  bucket = "my-logs"
  acl    = "private"
}

# New (AWS provider 4.x/5.x)
resource "aws_s3_bucket" "logs" {
  bucket = "my-logs"
}

resource "aws_s3_bucket_acl" "logs" {
  bucket = aws_s3_bucket.logs.id
  acl    = "private"
}

4. Convert attribute syntax to block syntax where the schema expects a block. Repeatable nested structures use a block (no =), not a map literal:

# Wrong — block written as an attribute
resource "aws_security_group" "web" {
  ingress = { from_port = 443, to_port = 443, protocol = "tcp" }
}

# Right — ingress is a nested block
resource "aws_security_group" "web" {
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

5. For module calls, match the declared variables. A module block only accepts arguments that the module declares as variable. Read the module’s variables.tf:

grep -h 'variable ' ./modules/network/*.tf

6. Re-run terraform validate until it returns success, then terraform plan.

Prevention and Best Practices

  • Pin provider versions with ~> and review the provider CHANGELOG before bumping a major version — major bumps are where arguments are renamed or removed.
  • Run terraform validate in CI on every pull request so schema errors fail fast, before plan.
  • Bookmark the provider docs at your exact version; the registry URL accepts a version path segment.
  • Use an editor with the Terraform language server (terraform-ls) so unknown arguments are flagged as you type.
  • When upgrading a major provider version, run the official upgrade guide and terraform plan in a throwaway workspace first.
  • Keep nested-block arguments (ingress, ebs_block_device, setting) as blocks, not map attributes.
  • Unsupported block type — the inverse: you wrote a block where the schema expects an attribute, or used a block name that does not exist.
  • Missing required argument — a required argument for the resource was omitted.
  • Reference to undeclared input variable — a module input or var. reference that has no matching variable block.
  • Invalid resource type — the resource type itself is not in the provider (often another version or wrong provider).

Frequently Asked Questions

Why does Terraform reject an argument that the AWS console clearly supports? Terraform validates against the provider’s schema, not the AWS API directly. If the provider version you pinned does not model that argument (or models it on a different resource), Terraform rejects it regardless of what the underlying service supports.

My code worked last month and now fails after terraform init. What changed? A terraform init with an unpinned or loosely pinned provider can pull a newer major version whose schema renamed or removed the argument. Check .terraform.lock.hcl and pin the version explicitly.

How do I find the correct argument name for my provider version? Run terraform providers schema -json and grep the resource’s attributes and block_types, or open the registry docs with the version selector set to your pinned version.

Is acl = "private" always wrong now? Not the value, the placement. On AWS provider 4.x and later, acl lives on the aws_s3_bucket_acl resource rather than aws_s3_bucket. Move it rather than deleting it.

Can I make Terraform ignore unknown arguments? No. There is no flag to ignore unknown arguments, by design — silently dropping a misspelled argument would hide configuration bugs. Fix the name or its placement.

Free download · 368-page PDF

Download the Free 500-Prompt DevOps AI Toolkit

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.