hashicorp/terraform · critical

resource not found in state

Error message

resource not found in state

What it means

findResourceInChildModules panics with 'resource not found in state' when ShowJSON.DisplayResourceInstanceState (internal/command/views/show.go:241) cannot locate the single resource it expects. It first scans each child module for exactly one resource, then recurses; if no branch yields a resource, it panics. The comment notes this should be unreachable because earlier validation should have rejected a missing resource.

Source

Thrown at internal/command/views/show.go:252

	if diags.HasErrors() {
		return 1
	}
	return 0
}

func findResourceInChildModules(mod jsonstate.Module) jsonstate.Resource {
	for _, cm := range mod.ChildModules {
		if len(cm.Resources) == 1 {
			return cm.Resources[0]
		}
	}
	for _, child := range mod.ChildModules {
		return findResourceInChildModules(child)
	}
	// this shouldn't be possible; we would have returned an error earlier if
	// the resource wasn't found.
	panic("resource not found in state")
}

View on GitHub (pinned to d32a084675)

Solutions

  1. Run 'terraform state list' to confirm the exact resource address and module path; re-run state show with the fully-qualified address returned there.
  2. If the address is valid but the resource is gone, 'terraform refresh'/'terraform apply -refresh-only' to reconcile state with reality, or restore a known-good state.
  3. Inspect the state with 'terraform state pull' to verify the module tree actually contains the expected resource instance.
  4. Report upstream: the panic means the earlier 'resource not found' diagnostic guard was bypassed, so include the state structure and the command that triggered it.

Example fix

// before
for _, child := range mod.ChildModules {
    return findResourceInChildModules(child)
}
panic("resource not found in state")

// after (return a zero value / signal to caller instead of panicking)
for _, child := range mod.ChildModules {
    if r, ok := findResourceInChildModulesOk(child); ok {
        return r, true
    }
}
return jsonstate.Resource{}, false
Defensive patterns

Strategy: validation

Validate before calling

// Before delegating to ShowJSON.DisplayResourceInstanceState, confirm the
// resource actually exists in the module tree.
func resourceExists(mod jsonstate.Module, addr string) bool {
    for _, r := range mod.Resources {
        if matchAddr(r, addr) {
            return true
        }
    }
    for _, cm := range mod.ChildModules {
        if resourceExists(cm, addr) {
            return true
        }
    }
    return false
}

Try / catch

defer func() {
    if r := recover(); r != nil {
        if msg, ok := r.(string); ok && strings.Contains(msg, "resource not found in state") {
            // surface a normal diagnostic instead of an uncaught panic
            diags = diags.Append(tfdiags.Sourceless(tfdiags.Error,
                "Resource not found", "The requested resource is not present in the current state."))
            return
        }
        panic(r)
    }
}()

Prevention

When it happens

Trigger: terraform state show <addr> where the state is non-empty (jsonState.Empty()==false), the root module has zero resources, and no descendant module at any depth holds exactly one resource (e.g. a module with 0 or 2+ resources at every level, or all child modules empty).

Common situations: State left behind by count=0/for_each-over-empty resources, a state file migrated or edited so the addressed resource sits in a module path the walker does not match, a race where state changed between address resolution and rendering, or a regression in the upstream guard that was supposed to return a diagnostic before reaching the view.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/e0d754bedc45732b. Report an issue: GitHub.