Error: Cycle - but not seeing why

Getting the following error, but I’m not seeing where the problem is:

│ Error: Cycle: module.workstation_fe.data.aws_iam_policy_document.sso_pre_sign_up, module.workstation_fe.data.aws_iam_policy_document.cognito_email, module.workstation_fe.local.lambda_functions (expand), module.workstation_fe.aws_cloudwatch_log_group.lambda_log_group

locals.tf:

  lambda_functions = {
    cognito_email = {
       ...
    }
    sso_pre_sign_up = {
       ...
    }
  }

cloudwatch.tf:

resource "aws_cloudwatch_log_group" "lambda_log_group" {
  for_each = local.lambda_functions

  name              = "/aws/lambda/${each.key}"
  retention_in_days = 180
}

data.tf:

data "aws_iam_policy_document" "cognito_email" {
  version = "2012-10-17"
  statement {
    effect = "Allow"
    actions = [
      ...
    ]
    resources = [aws_cloudwatch_log_group.lambda_log_group["cognito_email"].arn]
  }
  ]
}

data "aws_iam_policy_document" "sso_pre_sign_up" {
  version = "2012-10-17"
  statement {
    effect = "Allow"
    actions = [
      ...
    ]
    resources = [aws_cloudwatch_log_group.lambda_log_group["sso_pre_sign_up"].arn]
  }
  ]
}

Creating the log groups using the for_each isn’t causing a problem, i.e. it cycles through the locals variable and creates the log groups, but when I updated the resources element to reference the log group ARN rather than a wildcard declaration it reports the cycle error.

This appears to be a linear execution to me, so lost as to why it is reporting a cycle error, i.e. local.lambda_configs feeds in to aws_cloudwatch_log_group which feeds in to aws_iam_policy_document.

I’d appreciate any help offered.

Hi @glenn.comiskey,

I think we need some more information to try and track down what may be happening here. The configuration as shown should not produce any cycles, but because it isn’t complete, we can’t see all the possible references between these objects.

Dependencies don’t have to be directly between the objects, transitive dependencies can just as easily create cycles, but as the graph is simplified before it’s checked, some of those intermediate objects may not be shown in the error message. Also, since this is contained within a module, having module outputs eventually lead back to module inputs is another way to inadvertently create cycles in the configuration.

The first thing to check is that you are on a current release of Terraform, so that we can be sure no known bugs are contributing to the problem. Would it be possible to share a more complete example which reproduces the error?

The log output using TF_LOG_CORE=trace may help track down the issue, as it will show all dependencies and how where they’re derived. If it’s possible to share that in a github gist, we could take a look and see if it shows anything useful.

Thanks for the reply, jbardin, and for pointing out the logging features of Terraform.

As for the output and GitHub Gist, something else I’ve learned today, the trace output can be found at: Terrfaorm Cycle Error Log · GitHub

I am also trying to get Blast Radius to work, as this has been pointed out to me, but currently running in to issue getting that to work properly.

Thanks @glenn.comiskey,

According to the logs, module.workstation_fe.local.lambda_functions references module.workstation_fe.data.aws_iam_policy_document.cognito_email and module.workstation_fe.data.aws_iam_policy_document.sso_pre_sign_up, which would explain the cycle because those data sources reference the aws_cloudwatch_log_group which again references local.lambda_functions.

Thanks a lot for pointing out my mistake, jbardin, and sorry for wasting your time.

I’d got an image in my head of how the scripts were working, and couldn’t see the obvious mistake when looking at the file. Goes to show that preconceived ideas of how things work can be detrimental, and a second pay of eyes can be invaluable.

Thanks again.

One quick question, jbardin, given the wealth of information contained in the log file how did you narrow down the cyclic reference? Is there a keyword search that could be used, as when I briefly scanned the file I couldn’t readily see any fault but think it was because the output is too verbose. TIA.

Often I look at the internal graph output, but in this case the config was quite large so that would have taken some time to sort through.

There are log lines emitted when connecting references while building the graph, showing what nodes reference others. Since the only references we didn’t know from the sample config we’re from the locals, I just looked for what those reference in particular. Since this confirmed the exact same series of nodes shown in the cycle error, there wasn’t anything else to do.

If the cycle error was a reduced version of the actual cycle present in the configuration, it would have taken more effort to walk through the graph of nodes and a see how things are connected for the transitive reduction step removes the edges which may represent actual references from the configuration.