Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for OpenTofu By James Joyner IV · · 8 min read Last reviewed Jul 2026

OpenTofu Error: 'Self-referential block' resource referencing its own attributes

Quick answer

Fix OpenTofu's 'Self-referential block' error when a resource references its own attributes: break the cycle with locals, variables, or a separate resource.

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

Stuck on this OpenTofu error? Get the free incident triage checklist

A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.

Exact Error Message


│ Error: Self-referential block

│   on main.tf line 14, in resource "aws_security_group" "web":
│   14:   name = "${aws_security_group.web.id}-sg"

│ Configuration for aws_security_group.web may not refer to itself.

You may also see this surface as a cycle during tofu plan:

│ Error: Cycle: aws_security_group.web

What It Means

OpenTofu builds a dependency graph before it plans anything. Every reference like aws_security_group.web.id becomes an edge in that graph. When a resource argument refers back to an attribute of the same resource instance, OpenTofu cannot decide what to create first: the value it needs to build the resource depends on the resource already existing. That circular dependency is impossible to resolve, so OpenTofu rejects it up front with Self-referential block.

The confusing part is that the value often feels available (.id, .arn, .name), but those are computed attributes that only exist after the resource is created. Referencing them from within the same block asks OpenTofu to know the answer before it does the work.

Common Causes

  • Using a computed attribute of a resource (like .id or .arn) inside one of that same resource’s own arguments.
  • Building a name, tags, or description string from the resource’s own attributes.
  • A security group rule that references the group’s own id in an inline ingress/egress block (a genuinely common pattern that needs a separate resource).
  • Copy-pasting a reference from another resource and forgetting to change the resource label.
  • A module output that feeds back into an input consumed by the same resource.

Diagnostic Commands

Validate the configuration to surface the offending line and resource address:

tofu validate

Render the dependency graph to see the cycle visually:

tofu graph | grep -A2 -B2 "aws_security_group.web"

Search the file for every reference to the resource’s own address:

grep -n "aws_security_group.web" main.tf

Run a plan with detailed logging if the cycle only appears at plan time:

TF_LOG=trace tofu plan 2>&1 | grep -i "cycle\|self-ref"

Step-by-Step Resolution

  1. Find the exact argument that references the resource itself. The error’s on ... line N pointer is authoritative; start there.

  2. If you only need a static string, replace the self-reference with a plain literal or an input variable instead of the computed attribute:

variable "sg_name" {
  type    = string
  default = "web-sg"
}

resource "aws_security_group" "web" {
  name = var.sg_name
}
  1. If you need a derived value, compute it in a locals block that does not depend on the resource, then reference the local:
locals {
  sg_name = "web-${var.environment}-sg"
}

resource "aws_security_group" "web" {
  name = local.sg_name
}
  1. For the classic “a group that allows itself” case, do not reference the group’s id inline. Create a standalone rule resource that references the group after it exists:
resource "aws_security_group" "web" {
  name   = "web-sg"
  vpc_id = var.vpc_id
}

resource "aws_vpc_security_group_ingress_rule" "self" {
  security_group_id            = aws_security_group.web.id
  referenced_security_group_id = aws_security_group.web.id
  ip_protocol                  = "-1"
}
  1. Re-validate and plan to confirm the cycle is gone:
tofu validate && tofu plan

Prevention

  • Treat computed attributes (.id, .arn, anything not set literally in config) as read-only outputs, never as inputs to the same block.
  • Derive naming and tagging strings in locals or variables so they never reach back into a resource’s own attributes.
  • Split “resource references itself” patterns (self-allowing security groups, IAM role trust to its own ARN) into a dependent resource.
  • Run tofu validate in CI so self-references fail before merge, not during apply.
  • When you copy a block, immediately rename both the resource label and every reference inside it.
  • Cycle: ... — the more general dependency-cycle error, often the same root cause across two or more resources.
  • Reference to undeclared resource — you pointed at a resource address that does not exist.
  • Self-referential block in a dynamic block — the loop expression references the enclosing resource.
  • Invalid index — referencing a collection element that has not been created yet.

Frequently Asked Questions

Why can’t I use aws_security_group.web.id inside the same security group? Because .id is only known after the group is created, and the group cannot be created while an argument still waits on that value. Move the rule into a separate aws_vpc_security_group_ingress_rule resource.

Is a self-reference ever valid? No. OpenTofu always rejects a resource referencing its own attributes; you must break the loop with a literal, a variable, a local, or a separate resource.

How do I know which argument is the problem? The error prints on <file> line <N> pointing at the exact argument. tofu graph also shows the cycle if it spans multiple lines.

Can I use a local to compute a value from the resource itself? No. A local that references the resource inherits the same cycle. Locals must depend only on variables or other cycle-free values. For ready-made refactoring patterns, browse the prompt library for OpenTofu, and see more OpenTofu guides.

Free download · 368-page PDF

Fixed it? Get 500 OpenTofu & 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.

Did this fix your issue?

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.