For_each value depends on resource attributes results in multiple applies

I have a function app in a module which looks like this.

resource "azurerm_function_app" "app" {
  for_each = { for v in var.functions_metadata : v => v }

  name                      = format("%s%s%s%s%s", upper(var.environment_code), upper(var.deployment_code), upper(var.location_code), "-", each.key)
  location                  = data.azurerm_resource_group.rg.location
  resource_group_name       = data.azurerm_resource_group.rg.name
  app_service_plan_id       = azurerm_app_service_plan.service_plan.*.id[0]
  storage_connection_string = module.storage.primary_connection_string
  version                   = "~2"

  identity {
    type = "SystemAssigned"
  }

  app_settings = {
    WEBSITE_RUN_FROM_PACKAGE = var.appsetting_website_run_from_package
    FUNCTIONS_WORKER_RUNTIME = var.functions_worker_runtime
  }

I then have a output which looks like this

output "principal_ids" {
  value = length(azurerm_function_app.app) == 0 ? [] : [
    for f in keys(azurerm_function_app.app):
    (map("name", azurerm_function_app.app[f].name, "principal_id", azurerm_function_app.app[f].identity[0].principal_id))
  ] 
} 

I have a resource dependent on the above output ^.

resource "azurerm_role_assignment" "function_identity_to_storage" {
  for_each = { for v in module.warehouse-functions.principal_ids : v.name => v } 

  scope                = each.value.name
  role_definition_name = "Storage Blob Data Contributor"
  principal_id         = each.value.principal_id

  depends_on = [
    module.warehouse-functions.principal_ids
  ]
}

When i run a plan which creates a new function app throws this error:

Error: Invalid forEach argument

The "for_each" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the for_each depends on.

I don’t get this error if the function_app are created ahead of time, which is leading us to run multiple applies.

I have it nailed down to this azurerm_function_app.app[f].identity[0].principal_id in the output. If i replace it with a guid then all is good. :smiley:

I have tried to check for the length of azurerm_function_app.app[f].identity[0] and attempted to fake it out with a concat to a empty list but nothing works.

Any help would be appreciated.

The for_each value (map or set) must be known in advance of any remote resource actions.