Terraform State File Viewer

Read a state file without sending it anywhere. That matters more here than on any other page on this site: state holds the resolved value of every attribute, which means every secret the configuration touches.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Read. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A database password in state

Reported by attribute path only, and the value is never shown

{
  "version": 4,
  "serial": 1,
  "resources": [
    {
      "mode": "managed",
      "type": "aws_db_instance",
      "name": "main",
      "instances": [
        { "attributes": { "identifier": "main", "password": "REPLACE_ME" } }
      ]
    }
  ]
}

A tainted instance

Destroyed and recreated on the next apply, with nothing in the configuration to explain it

{
  "version": 4,
  "serial": 1,
  "resources": [
    {
      "mode": "managed",
      "type": "aws_instance",
      "name": "web",
      "instances": [{ "tainted": true, "attributes": { "id": "i-1" } }]
    }
  ]
}

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Assuming sensitive keeps a value out of state

    sensitive affects terminal output only. The plaintext value is written to state regardless, so anybody who can read the file can read every generated secret.

    Instead:Protect read access to state as tightly as the secrets themselves: encrypted backend, restricted bucket or workspace, and rotate anything that has been in a less protected copy.

  2. Removing a deposed entry from state to stop the errors

    The object still exists in the cloud. Removing it from state means Terraform stops trying to destroy it and stops knowing about it, so it is billed forever with nothing tracking it.

    Instead:Find out why the delete is being refused. Dependencies and deletion protection are the usual causes.

  3. Splitting a large state by team

    Plan time follows the number of instances, and team boundaries do not match dependency boundaries, so you get the same slow plans plus cross-state references.

    Instead:Split by lifecycle: things that change together stay together. Join them with data sources.

sensitive controls what Terraform prints, not what it writes

This is the single most consequential misunderstanding about state, and it is the reason a state file deserves the same protection as the secrets inside it.

Every attribute value is stored in full

A generated password, a private key, a connection string, a token returned by an API: state records the resolved value. Marking a variable or an output sensitive changes the terminal output and nothing about the file. So read access to state is read access to all of it, and a state file copied to a laptop for debugging is a copy of every credential.

A tainted instance is replaced with no reason visible in the diff

Terraform marks an instance tainted when a provisioner fails, and the next apply destroys and recreates it. Nothing in the configuration changed, so the plan looks unexplained until you know to look for the mark. terraform untaint clears it.

A deposed object still exists and is still being billed

It is the old instance from a create_before_destroy replacement whose destroy step did not complete. Terraform will retry the destroy on the next apply. If the destroy keeps failing and somebody removes the entry from state to make the noise stop, the object is orphaned and billed indefinitely.

Instance count is what plan time tracks, not resource count

One resource with a for_each over three hundred items is three hundred instances, all read and refreshed on every plan. Past a few hundred, a one-line change takes minutes, and a bad apply has the whole file as its blast radius.

Serial and lineage are why restoring a backup by copying fails

The serial increments on every write and the lineage identifies the state's history. Copying an older file into place moves the serial backwards, which a backend that tracks it will refuse, and a state with a different lineage is rejected outright. terraform state push handles both.

Terraform refuses state written by a newer version than itself

So the moment one person runs a newer binary, everyone else is blocked until they upgrade. The error names the version rather than the person, and it is entirely avoidable by pinning the version everybody uses.