OpenTofu Error: 'Self-referential block' resource referencing its own attributes
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
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
.idor.arn) inside one of that same resource’s own arguments. - Building a
name,tags, ordescriptionstring from the resource’s own attributes. - A security group rule that references the group’s own
idin an inlineingress/egressblock (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
-
Find the exact argument that references the resource itself. The error’s
on ... line Npointer is authoritative; start there. -
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
}
- If you need a derived value, compute it in a
localsblock 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
}
- For the classic “a group that allows itself” case, do not reference the group’s
idinline. 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"
}
- 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
localsor 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 validatein 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.
Related Errors
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 blockin adynamicblock — 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.
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?
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.