The true and false result expressions must have consistent types Error

So I have the following code and get the following error:

managed_rules = {
    rds_storge_encrypted = {
      identifier  = "RDS_STORAGE_ENCRYPTED"
      description = "Checks whether storage encryption is enabled for your RDS DB instances."
      input_parameters = {
        kmsKeyId : 123
      }
      enabled                     = "true"
      applies_to_global_resources = "false"
    },
    encrypted_volumes = {
      identifier  = "VPC_SG_OPEN_ONLY_TO_AUTHORIZED_PORTS"
      description = "Checks if security groups allowing unrestricted incoming traffic ('0.0.0.0/0' or '::/0') only allow inbound TCP or UDP connections on authorized ports."
      input_parameters = {
        authorizedTcpPorts : "456"
        authorizedUdpPorts : "789"
      }
      enabled                     = "true"
      applies_to_global_resources = "false"
    }
}

resource "aws_config_organization_managed_rule" "rules" {
  for_each = !var.create_account_rules ? local.rules_to_process :{}

  name             = each.key
}```

This results in the following error:

```Error: Inconsistent conditional result types
│ 
│   on .terraform/modules/baseline.aws_config_multi_region/modules/krrv-sca-aws-config-rules/main.tf line 81, in resource "aws_config_organization_managed_rule" "rules":
│   81:   for_each = !var.create_account_rules ? local.rules_to_process :{}
│     ├────────────────
│     │ local.rules_to_process is object with 8 attributes
│     │ var.create_account_rules is true
│ 
│ The true and false result expressions must have consistent types. The
│ 'true' value includes object attribute "encrypted_volumes", which is absent
│ in the 'false' value.
╵
╷
│ Error: Inconsistent conditional result types
│ 
│   on .terraform/modules/baseline.aws_config_multi_region/modules/krrv-sca-aws-config-rules/main.tf line 93, in resource "aws_config_config_rule" "rules":
│   93:   for_each = var.create_account_rules ? local.rules_to_process : {}
│     ├────────────────
│     │ local.rules_to_process is object with 8 attributes
│     │ var.create_account_rules is true
│ 
│ The true and false result expressions must have consistent types. The
│ 'true' value includes object attribute "encrypted_volumes", which is absent
│ in the 'false' value.```

Why does it think the local variable is an object with x attributes rather than a map and how to supply and empty map as the false value.

I am unable to reproduce the problem you are experiencing using the code you posted.

You have not posted the definition of local.rules_to_process, and guessing that you meant local.managed_rules (and left out the enclosing locals {} block around that), results in code that works fine for me.

oops heres the missing local

rules_to_process = { for k, v in local.managed_rules : k => v if lookup(v, "enabled", true) && (v.applies_to_global_resources == false || var.enable_global_resource_rules) && !var.create_account_rules }

Complete Code:

variable "additional_rules" {
  description = "Map of additional managed rules to add. The key is the name of the rule (e.g. ´acm-certificate-expiration-check´) and the value is an object specifying the rule details"
  type = map(object({
    description = string
    identifier = string
    trigger_type = string
map ´{}´.
    input_parameters = map(string)
    applies_to_global_resources = bool
  }))
  default = {}
}

locals {
  managed_rules = merge(
    {
      "rds_storge_encrypted" = {
        identifier  = "RDS_STORAGE_ENCRYPTED"
        description = "Checks whether storage encryption is enabled for your RDS DB instances."
        input_parameters = {
          kmsKeyId : "${var.rds_storage_encrypted_kms_id}"
        }
        enabled                     = "${var.enable_rds_storage_encrypted}"
        applies_to_global_resources = "false"
      },
      "encrypted_volumes" = {
        identifier  = "EFS_ENCRYPTED_CHECK"
        description = "Checks if Amazon Elastic File System (Amazon EFS) is configured to encrypt the file data using AWS Key Management Service (AWS KMS)."
        input_parameters = {
          kmsKeyId : "${var.encrypted_volumes_kms_id}"
        }
        enabled                     = "${var.enable_encrypted_volumes}"
        applies_to_global_resources = "false"
      }
    }
  , var.additional_rules)

  rules_to_process = { for k, v in local.managed_rules : k => v if lookup(v, "enabled", true) && (v.applies_to_global_resources == false || var.enable_global_resource_rules) && !var.create_account_rules }
}

resource "aws_config_organization_managed_rule" "rules" {
  for_each = !var.create_account_rules ? local.rules_to_process : {}

  name             = each.key
  description      = each.value.description
  rule_identifier  = each.value.identifier
  input_parameters = length(each.value.input_parameters) > 0 ? jsonencode(each.value.input_parameters) : null

  maximum_execution_frequency = var.maximum_execution_frequency
  excluded_accounts           = var.excluded_accounts
}

resource "aws_config_config_rule" "rules" {
  for_each = var.create_account_rules ? local.rules_to_process : null

  name             = each.key
  description      = each.value.description
  input_parameters = lookup(each.value, "input_parameters", null) != null && length(each.value.input_parameters) > 0 ? jsonencode(each.value.input_parameters) : null

  maximum_execution_frequency = var.maximum_execution_frequency
  source {
    owner             = "AWS"
    source_identifier = each.value.identifier
  }
}

I had to delete this line, which looks like bad copy/paste:

Add some placeholder variables:

variable "rds_storage_encrypted_kms_id" { default = 123 }
variable "enable_rds_storage_encrypted" { default = true }
variable "encrypted_volumes_kms_id" { default = 123 }
variable "enable_encrypted_volumes" { default = true }
variable "create_account_rules" { default = false }
variable "enable_global_resource_rules" { default = true }

rewrite the AWS resources to null_resource:

resource "null_resource" "rules" {
  for_each = !var.create_account_rules ? local.rules_to_process : {}
}

resource "null_resource" "rules2" {
  for_each = var.create_account_rules ? local.rules_to_process : {}
}

including fixing the incorrect use of null in a for_each:

but having done all that… it runs fine. I’m still not getting the error you are.

I’m using Terraform 1.4.6.

Yep that was a bad copy\paste

I just tried using a null to see if it would fix the issue