'Error: Incorrect attribute value type. Inappropriate value for attribute "name": string required

I'm unable to create 4 subnets within a vnet using type = list(map(string))

Error: Incorrect attribute value type
│
│   on .terraform/modules/subnet1-app1/virtual-network/subnet/main.tf line 3, in resource "azurerm_subnet" "subnet":
│    3:   name                 = var.subnet_name
│     ├────────────────
│     │ var.subnet_name is a list of map of string, known only after apply
│
│ Inappropriate value for attribute "name": string required.



boilerplate

        |_ providers.tf
        |_ locals.tf
        |_ resource_groups.tf
        |_ vnets.tf
        |_ subnets.tf
        |_ terraform.tfvars
        |_ variables.tf
    
    modules
    |_ resource-group
              |_ main.tf
              |_ outputs.tf
              |_ variables.tf

    |_ virtual-network
              |_ main.tf
              |_ outputs.tf
              |_ variables.tf

          |_ subnet
              |_ main.tf
              |_ outputs.tf
              |_ variables.tf

modules/terraform-azure-module-resourcegroup/main.tf

resource "azurerm_resource_group" "rg" {
  name     = var.resource_group_name
  location = var.location
  tags     = var.tags
}

modules/terraform-azure-module-resourcegroup/outputs.tf

# Output Variables of the module

output "resource_group_name" {
  value       = azurerm_resource_group.rg.name
  description = "name of resource group"
}

output "location" {
  value       = azurerm_resource_group.rg.location
  description = "location of resource group"
}

modules/terraform-azure-module-resourcegroup/variables.tf

# Input Variables of the module

variable "resource_group_name" {
  type        = string
  description = "name of resource group"
}

variable "location" {
  type        = string
  description = "location of resource group"
}

variable "tags" {
  type    = map(any)
  default = {}
}

modules/terraform-azure-module-network/virtual-network/main.tf

# Create the Virtual Network
resource "azurerm_virtual_network" "vnet" {
  name                = var.vnet_name
  location            = var.vnet_location
  resource_group_name = var.resource_group_name
  address_space       = var.vnet_address_space
  dns_servers         = var.dns_servers
}

modules/terraform-azure-module-network/virtual-network/outputs.tf

# Vnet Outputs

# output "vnet_id" {
#   description = "The id of the newly created vNet"
#   value       = azurerm_virtual_network.vnet.id
# }

output "vnet_name" {
  description   = "The Name of the newly created vNet"
  value         = azurerm_virtual_network.vnet.name
}

output "vnet_location" {
  description   = "The location of the newly created vNet"
  value         = azurerm_virtual_network.vnet.location
}

# output "vnet_address_space" {
#   description   = "The address space of the newly created vNet"
#   value         = azurerm_virtual_network.vnet.address_space
# }

modules/terraform-azure-module-network/virtual-network/variables.tf

# Vnet Variables

variable "vnet_location" {
  type        = string
  description = "Location of environment"
}

variable "resource_group_name" {
  type        = string
  description = "name of resource group"
}

variable "vnet_name" {
  type        = string
  description = "Name of Virtual Network"
}

variable "vnet_address_space" {
  type        = list(any)
  description = "Address space of Virtual Network"
}

variable "dns_servers" {
  type        = list(any)
  description = "Dns servers for Virtual Network"
}

modules/terraform-azure-module-network/virtual-network/subnet/main.tf

# Create the Subnet
resource "azurerm_subnet" "subnet" {
  name                 = var.subnet_name
  resource_group_name  = var.resource_group_name
  virtual_network_name = var.vnet_name
  address_prefixes     = var.subnet_address_prefixes
}

modules/terraform-azure-module-network/virtual-network/subnet/variables.tf

variable "subnet_name" {
# type = map(string)
# type        = string
type        = list(map(string))
}

variable "resource_group_name" {
  type        = string
  description = "name of resource group"
}

variable "subnet_address_prefixes" {
  type                 = list(any)
  description          = "Address prefixes of Subnet"
}

variable "vnet_name" {
  type                 = string
  description          = "Name of Virtual Network"
}

subscriptions/boilerplate/providers.tf

# Terraform Block
terraform {
  required_version = ">= 1.0.0"
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">= 2.0"
    }
  }
}

# Provider Block
provider "azurerm" {
  subscription_id = "*"
  features {}
}

subscriptions/boilerplate/locals.tf

locals {
  resource_group_name = "rg-${var.environment}-${var.project_office}-${var.asset_name}"
  vnet_name           = "vn-${var.environment}-${var.project_office}-${var.asset_name}"
  location            = var.location
}

subscriptions/boilerplate/resource_groups.tf

module "rg-app1" {
  source = "git::ssh://[email protected]/v3/*/*/terraform-azure-module-resourcegroup"
  resource_group_name = local.resource_group_name
  location            = local.location
  tags                = var.tags

}

subscriptions/boilerplate/networking.tf

module "vnet-app1" {
  source              = "git::ssh://[email protected]/v3/*/*/terraform-azure-module-network//virtual-network"
  vnet_name           = local.vnet_name
  vnet_location       = module.rg-app1.location
  resource_group_name = module.rg-app1.resource_group_name
  vnet_address_space  = var.vnet_address_space
  dns_servers         = var.dns_servers

  depends_on = [module.rg-app1]
}


module "subnet1-app1" {
  source = "git::ssh://[email protected]/v3/*/*/terraform-azure-module-network//virtual-network/subnet"
  for_each = var.subnet_name

  resource_group_name     = module.rg-app1.resource_group_name
  vnet_name               = module.vnet-app1.vnet_name
  subnet_name             = each.value.name
  subnet_address_prefixes = each.value.subnet_address_prefixes

  depends_on = [
    module.rg-app1,
    module.vnet-app1
  ]
}

subscriptions/boilerplate/terraform.tfvars

location       = "Australia Southeast"
environment    = "d"
project_office = "O1"
asset_name     = "boilerplate"

tags = {
  env     = "dev"
  project = "azure refresh"
}

vnet_address_space = ["10.1.0.0/16"]
dns_servers        = ["1.1.1.1", "4.4.4.4"]

# subnet_address_prefixes = ["10.1.0.0/24"]

subnet_name = [
  {
    name                    = "web"
    subnet_address_prefixes = "10.1.1.0/24"
  },
  {
    name                    = "app"
    subnet_address_prefixes = "10.1.2.0/24"
  },
  {
    name                    = "data"
    subnet_address_prefixes = "10.1.3.0/24"
  },
  # The name must be AzureBastionSubnet
  {
    name             = "AzureBastionSubnet"
    address_prefixes = "10.1.250.0/24"
  }
]

subscriptions/boilerplate/variables.tf

# Resource Group Variables

variable "location" {
  type        = string
  description = "location of resource group"
}

variable "tags" {
  type    = map(any)
  default = {}
}

variable "project_office" {
  description = "Project Office Name"
  type        = string
}

variable "environment" {
  description = "Environment Name"
  type        = string
}

variable "asset_name" {
  description = "Project Office Name"
  type        = string
}

# Vnet & Subnet Variables

variable "vnet_address_space" {
  type        = list(any)
  description = "Address space of Virtual Network"
}

variable "dns_servers" {
  type        = list(any)
  description = "Dns servers for Virtual Network"
}

variable "subnet_name" {
  # type = map(string)
  type        = list(map(string))
}

Error message when enabling export TF_LOG=DEBUG

[ERROR] vertex "module.subnet1-app1.azurerm_subnet.subnet" error: Incorrect attribute value type


Solution 1:[1]

The error you've shared is for the commented out line, which is obvious since it is supplying list for attribute expecting a string.

In the new line for this attribute, you have:

subnet_name             = each.value.subnet_name

But it should be:

subnet_name             = each.value.name

Because 'name' is part of the map, not subnet_name. subnet_name is name of the variable.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1