How to fix terragrunt plan error messages regarding for_each

I’m unsure what I’m doing wrong. I have terraform module code below ,I want to create 2 SQS with deadletter queue for each SQS together with necessary policy for SQS and DeadQueue.

resource "aws_sqs_queue" "CloudTrail_SQS"{

    for_each                   = var.sqs_queue_names
    name                       = each.value
    visibility_timeout_seconds = var.visibility_timeout_seconds
    max_message_size           = var.max_message_size
    message_retention_seconds  = var.message_retention_seconds
    delay_seconds              = var.delay_seconds
    receive_wait_time_seconds  = var.receive_wait_time_seconds
    redrive_policy = jsonencode({
        deadLetterTargetArn    = aws_sqs_queue.CloudTrail_SQS_DLQ[each.key].arn
        maxReceiveCount        = var.max_receive_count
    })

    tags = var.default_tags
    
}

resource "aws_sqs_queue" "CloudTrail_SQS_DLQ"{

    for_each                   = var.dead_queue_names
    name                       = each.value
    visibility_timeout_seconds = var.visibility_timeout_seconds
    max_message_size           = var.max_message_size
    message_retention_seconds  = var.message_retention_seconds
    delay_seconds              = var.delay_seconds
    receive_wait_time_seconds  = var.receive_wait_time_seconds

    tags = var.default_tags
}
    
data "aws_iam_policy_document" "policy_document"{
  statement{
    actions = [
      "sqs:DeleteMessage",
      "sqs:GetQueueUrl",
      "sqs:ReceiveMessage",
      "sqs:SendMessage",
      "sqs:SetQueueAttributes"
    ]
    effect = "Allow"
    resources =[
      "${aws_sqs_queue.CloudTrail_SQS[each.key].arn}"
    ]
  }

     resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy" {
         queue_url = aws_sqs_queue.CloudTrail_SQS[each.key].id

      policy = <<POLICY
   {
      "Version": "2012-10-17",
     "Id": "sqspolicy"
    "Statement": [
    {
      "Sid": "AllowSQSInvocation",
      "Effect": "Allow",
      "Principal": {"AWS":"*"},
      "Action": "sqs:*",
      "Resource": "${aws_sqs_queue.CloudTrail_SQS[each.key].arn}"

Below is my terragrunt.hcl

terraform {
  source = "../../../../..//module"
}


include {
  path = find_in_parent_folders()
}

inputs = {
  cloudtrail_event_log_bucket_name = "aws-cloudtrailbucket-sqs-logs"
  sqs_queue_names                  = ["CloudTrail_Event_One", "CloudTrail_SQS_Event_Two"]
  dead_queue_names                 = ["CloudTrail_DLQ_Event_One", "CloudTrail_DLQ_Event_Two"]
  } 

My terragrunt plan returns this. it complains about for_each, but unsure what to do with it.
these are some of the error me:

1.....on iam.tf line 2, in resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy":
│    2:   queue_url = aws_sqs_queue.CloudTrail_SQS.id
│ 
│ Because aws_sqs_queue.CloudTrail_SQS has "for_each" set, its attributes
│ must be accessed on specific instances.
│ 
│ For example, to correlate with indices of a referring resource, use:
│     aws_sqs_queue.CloudTrail_SQS[each.key]

2.....  Missing resource instance key
│ 
│   on iam.tf line 14, in resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy":
│   14:       "Resource": "${aws_sqs_queue.CloudTrail_SQS.arn}",
│ 
│ Because aws_sqs_queue.CloudTrail_SQS has "for_each" set, its attributes
│ must be accessed on specific instances.
│ 
│ For example, to correlate with indices of a referring resource, use:
│     aws_sqs_queue.CloudTrail_SQS[each.key]

3...Error: Missing resource instance key
│ 
│   on output.tf line 10, in output "sqs_queue_arn":
│   10:   value       =  aws_sqs_queue.CloudTrail_SQS.arn
│ 
│ Because aws_sqs_queue.CloudTrail_SQS has "for_each" set, its attributes
│ must be accessed on specific instances.

Hi @darekorex!

I tried to find in your code snippets the specific lines that are included in the error messages, but I couldn’t find it. Is there another part of the configuration you didn’t include, which these error messages are referring to?

Since Terragrunt isn’t a HashiCorp project we can’t directly help with that here, but fortunately in this case I don’t think that’s important because it seems like what you have is essentially equivalent to directly running Terraform CLI with a .tfvars file containing the following:

cloudtrail_event_log_bucket_name = "aws-cloudtrailbucket-sqs-logs"
sqs_queue_names                  = ["CloudTrail_Event_One", "CloudTrail_SQS_Event_Two"]
dead_queue_names                 = ["CloudTrail_DLQ_Event_One", "CloudTrail_DLQ_Event_Two"]

I’m going to assume that’s true while we work on this, but if that doesn’t seem like a valid assumption based on what you know about Terragrunt then please let me know!

each.key can only be used in conjunction with for_each.

In your case, aws_sqs_queue_policy. Cloudtrail_SQS_Policy and aws_iam_policy_document. policy_document doesn’t have for_each, so you can’t use them there.

you may want to use keys function in those two resources.

my code snippet and the correspondent error message below

```
resource "aws_sqs_queue" "CloudTrail_SQS"{

       for_each                   = var.sqs_queue_names
      name                       = each.value
     redrive_policy = jsonencode({
        deadLetterTargetArn    = aws_sqs_queue.CloudTrail_SQS_DLQ[each.key].arn
        maxReceiveCount        = var.max_receive_count
    })
}

~~~ Error: Missing resource instance key on deadLetterTargetArn



```
resource "aws_sqs_queue" "CloudTrail_SQS_DLQ"{

    for_each                   = var.dead_queue_names
    name                       = each.value
}

~~~ Error: Missing resource instance key

~~~resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy" {
  queue_url = aws_sqs_queue.CloudTrail_SQS[each.key].id

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Id": "sqspolicy",
  "Statement": [
    {
      "Sid": "AllowSQSInvocation",
      "Effect": "Allow",
      "Principal": {"AWS":"*"},
      "Action": "sqs:*",
      "Resource": "${aws_sqs_queue.CloudTrail_SQS[each.key].arn}"

~~~on iam.tf line 14, in resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy":
│   14:       "Resource": "${aws_sqs_queue.CloudTrail_SQS.arn}",
│ 
│ Because aws_sqs_queue.CloudTrail_SQS has "for_each" set, its attributes
│ must be accessed on specific instances.


~~~data "aws_iam_policy_document" "policy_document"{
  statement{
    actions = [
      "sqs:ReceiveMessage",
      "sqs:SendMessage"
    ]
    effect = "Allow"
    resources =[
      "${aws_sqs_queue.CloudTrail_SQS[each.key].arn}"

error message:
~~~on iam_role.tf line 40, in data "aws_iam_policy_document" "policy_document":
│ 40: "${aws_sqs_queue.CloudTrail_SQS[each.key].arn}"
│
│ The "each" object can be used only in "module" or "resource" blocks, and
│ only when the "for_each" argument is set.

~~~output "sqs_queue_arn" {
  value       =  aws_sqs_queue.CloudTrail_SQS.arn
  description = "The ARN of the SQS queue."
}

Error message:
~~~.Error: Missing resource instance key
│ 
│   on output.tf line 10, in output "sqs_queue_arn":
│   10:   value       =  aws_sqs_queue.CloudTrail_SQS.arn
│ 
│ Because aws_sqs_queue.CloudTrail_SQS has "for_each" set, its attributes
│ mu

@ausmartway please if you don’t mind can you suggest how to use keys function in my case?and why I am getting the same error on my resource below

data "aws_iam_policy_document" "policy_document"{
    statement{
   actions = [
     "sqs:DeleteMessage",
    "sqs:GetQueueUrl",
   "sqs:ReceiveMessage",
   "sqs:SendMessage",
  "sqs:SetQueueAttributes"
]
effect = "Allow"
resources =[
  "${aws_sqs_queue.Trail_SQS.arn}"
]

```
resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy" {
  queue_url = aws_sqs_queue.CloudTrail_SQS[each.key].id

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Id": "sqspolicy",
  "Statement": [
    {
      "Sid": "AllowSQSInvocation",
      "Effect": "Allow",
      "Principal": {"AWS":"*"},
      "Action": "sqs:*",
      "Resource": "${aws_sqs_queue.CloudTrail_SQS[each.key].arn}
```
thanks indvance

@apparentlymart below is my complete code that terraform is complaining about accessing specific attribute of the instances and below my code is the error generated

Terragrunt.hcl == .tfvars

sqs_queue_name  =  ["CloudTrail_Event_One", "CloudTrail_SQS_Event_Two"]
dead_queue_names = ["CloudTrail_DLQ_Event_One", "CloudTrail_DLQ_Event_Two"]

variable.tf

variable "sqs_queue_names"{
     description = "the name of queues to be created"
     type             = set(string)
}
variable "dead_queue_names"{
     description = "the name of  dead queues to be created"
     type             = set(string)
}
output.tf
  output "dead_letter_queue_arn" {
  value       =  aws_sqs_queue.CloudTrail_SQS_DLQ.arn
  description = "The ARN of the dead queue."
}
output "sqs_queue_url"{
  description = "The URL for the created Amazon SQS queue"
  value       = aws_sqs_queue.CloudTrail_SQS.url
}
   output "dead_letter_queue_url"{
  value = aws_sqs_queue.CloudTrail_SQS_DLQ.url
  description = "The URL for the created dead letter queue"
}
output "sqs_queue_arn" {
  value       =  aws_sqs_queue.CloudTrail_SQS.arn
  description = "The ARN of the SQS queue."
}

resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy" {
  queue_url = aws_sqs_queue.CloudTrail_SQS.id

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Id": "sqspolicy",
  "Statement": [
    {
      "Sid": "AllowSQSInvocation",
      "Effect": "Allow",
      "Principal": {"AWS":"*"},
      "Action": "sqs:*",
      "Resource": "${aws_sqs_queue.CloudTrail_SQS.arn}"


resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy" {
  queue_url = aws_sqs_queue.CloudTrail_SQS.id

  policy = <<POLICY
{
  "Version": "2012-10-17",
  "Id": "sqspolicy",
  "Statement": [
    {
      "Sid": "AllowSQSInvocation",
      "Effect": "Allow",
      "Principal": {"AWS":"*"},
      "Action": "sqs:*",
      "Resource": "${aws_sqs_queue.CloudTrail_SQS.arn}"


resource "aws_sqs_queue" "CloudTrail_SQS"{

    for_each                   = var.sqs_queue_names
    name                       = each.value
    redrive_policy = jsonencode({
        deadLetterTargetArn    = aws_sqs_queue.CloudTrail_SQS_DLQ[each.key].arn
        maxReceiveCount        = var.max_receive_count
    })
}


resource "aws_sqs_queue" "CloudTrail_SQS_DLQ"{

    for_each                   = var.dead_queue_names
    name                       = each.value
}

Error messages generated

1.....Error: Missing resource instance key
│
│ on iam.tf line 2, in resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy":
│ 2: queue_url = aws_sqs_queue.CloudTrail_SQS.id
│
│ Because aws_sqs_queue.CloudTrail_SQS has "for_each" set, its attributes
│ must be accessed on specific instances.
│
│ For example, to correlate with indices of a referring resource, use:
│ aws_sqs_queue.CloudTrail_SQS[each.key]

2...Error: Missing resource instance key
│
│ on iam.tf line 14, in resource "aws_sqs_queue_policy" "Cloudtrail_SQS_Policy":
│ 14: "Resource": "${aws_sqs_queue.CloudTrail_SQS.arn}",
│
│ Because aws_sqs_queue.CloudTrail_SQS has "for_each" set, its attributes
│ must be accessed on specific instances.
│
│ For example, to correlate with indices of a referring resource, use:
│ aws_sqs_queue.CloudTrail_SQS[each.key]

3.........
Error: Reference to "each" in context without for_each
│
│ on iam.tf line 27, in resource "aws_sqs_queue_policy" "CloudTrail_SQS_DLQ":
│ 27: queue_url = aws_sqs_queue.CloudTrail_SQS_DLQ[each.key].id
│
│ The "each" object can be used only in "module" or "resource" blocks, and
│ only when the "for_each" argument is set.

4...Error: Reference to "each" in context without for_each
│
│ on iam_role.tf line 40, in data "aws_iam_policy_document" "securonix_policy_document":
│ 40: "${aws_sqs_queue.CloudTrail_SQS[each.key].arn}"
│
│ The "each" object can be used only in "module" or "resource" blocks, and
│ only when the "for_each" argument is set.

thank you indvance for looking into this for me

your aws_sqs_queue_policy should look like this:

resource “aws_sqs_queue_policy” “Cloudtrail_SQS_Policy” {
for_each = var.sqs_queue_names
queue_url = aws_sqs_queue.CloudTrail_SQS**[each.key]**.id

policy = <<POLICY
{
“Version”: “2012-10-17”,
“Id”: “sqspolicy”,
“Statement”: [
{
“Sid”: “AllowSQSInvocation”,
“Effect”: “Allow”,
“Principal”: {“AWS”:""},
“Action”: "sqs:
",
“Resource”: “${aws_sqs_queue.CloudTrail_SQS**[each_key]**.arn}”

Thank you so much,it worked.However,i am still receiving the same error message for :

data "aws_iam_policy_document" "policy_document"{
    statement{
   actions = [
     "sqs:DeleteMessage",
    "sqs:GetQueueUrl",
   "sqs:ReceiveMessage",
   "sqs:SendMessage",
  "sqs:SetQueueAttributes"
]
effect = "Allow"
resources =[
  "${aws_sqs_queue.Trail_SQS.arn}

is there a way I can call the value of aws_sqs_queue.Trail_SQS.arn  in the resource element which will then return the 2 SQS created using for_each?

I guess you want this:

data "aws_iam_policy_document" "policy_document"{
 for_each= var.sqs_queue_names
    statement{
   actions = [
     "sqs:DeleteMessage",
    "sqs:GetQueueUrl",
   "sqs:ReceiveMessage",
   "sqs:SendMessage",
  "sqs:SetQueueAttributes"
]
effect = "Allow"
resources =[

  "${aws_sqs_queue.Trail_SQS[each.key].arn},
"${aws_sqs_queue.Trail_SQS_DLQ[each.key].arn},
]
}