Terraform cidrsubnet calculator and function tester

Paste the call you already wrote. This runs cidrsubnet, cidrsubnets, cidrhost and cidrnetmask with Terraform's own rules and shows what each one returns — or the error Terraform prints and why.

Runs entirely in your browser. Your data is never uploaded.

Write them as they appear in your configuration. A whole line such as subnet_cidr = cidrsubnet("10.0.0.0/16", 8, 2) works, and # comments are skipped. Values must be literal: this cannot resolve var.… or local.… references.

Examples

    What the three arguments do

    cidrsubnet(prefix, newbits, netnum) takes a network and carves a smaller one out of it.

    Worked examples

    CallResultWhat it shows
    cidrsubnet("10.0.0.0/16", 8, 2) 10.0.2.0/24 Eight more bits make a /24; netnum 2 fills them with 2.
    cidrsubnet("10.0.1.5/16", 8, 2) 10.0.2.0/24 The host bits of the parent (.1.5) are masked away first, silently.
    cidrsubnet("10.0.0.0/16", 0, 0) 10.0.0.0/16 newbits of 0 returns the parent unchanged.
    cidrsubnet("10.0.0.0/16", -8, 0) 10.0.0.0/8 Negative newbits shorten the prefix, giving a network that is not inside the parent.
    cidrsubnet("fd00:fd12:3456:7890::/56", 16, 162) fd00:fd12:3456:7800:a200::/72 IPv6 works the same way; 162 is written into the 16 new bits.
    cidrsubnets("10.1.0.0/16", 4, 4, 8, 4) 10.1.0.0/20, 10.1.16.0/20, 10.1.32.0/24, 10.1.48.0/20 Consecutive subnets of different sizes, each aligned to its own boundary.
    cidrhost("10.12.112.0/20", 16) 10.12.112.16 The 17th address in the range (offsets start at 0).
    cidrhost("10.12.112.0/20", -1) 10.12.127.255 A negative hostnum counts back from the end, so -1 is the last address.
    cidrnetmask("172.16.0.0/12") 255.240.0.0 The dotted-quad mask for a prefix length. IPv4 only.

    The errors, and what they actually mean

    Terraform prints these inside a Call to function "cidrsubnet" failed: diagnostic. The wording below is the part that varies, reproduced exactly, so you can paste a failing call above and read the same sentence with an explanation next to it.

    CallMessageWhy
    cidrsubnet("10.0.0.0/16", 8, 256) prefix extension of 8 does not accommodate a subnet numbered 256 8 new bits number subnets 0–255, so 256 does not fit. The highest netnum is always 2^newbits − 1.
    cidrsubnet("10.0.0.0/16", 24, 0) insufficient address space to extend prefix of 16 by 24 16 + 24 is longer than an IPv4 address. The limit is 32 bits in total, or 128 for IPv6.
    cidrsubnets("10.0.0.0/16", 1, 1, 1) invalid argument 3: not enough remaining address space for a subnet with a prefix of 17 bits after 10.0.128.0/17 Two /17s already fill the /16. cidrsubnets allocates in order and never reuses space.
    cidrhost("10.0.0.0/24", 256) prefix of 24 does not accommodate a host numbered 256 A /24 holds 256 addresses, numbered 0–255.
    cidrnetmask("fd00::/8") IPv6 addresses cannot have a netmask: fd00::/8 cidrnetmask is IPv4 only; IPv6 has no dotted-quad mask form.
    cidrsubnet("10.0.0.0/33", 8, 1) invalid CIDR expression: invalid CIDR address: 10.0.0.0/33 The prefix length is checked before anything else. Watch for /33 typed instead of /32.

    Three things that surprise people

    Host bits in the parent are thrown away, silently

    cidrsubnet("10.0.1.5/16", 8, 2) is not an error. The prefix is masked to 10.0.0.0/16 before anything else happens, so the answer is the same as for a clean parent. If a variable holds an address rather than a network, you will get a plausible result computed from a network you did not mean. The tester says so whenever it applies.

    Negative newbits give you a network outside the parent

    Terraform accepts a negative newbits, which makes the prefix shorter, so the result is not contained in the network you passed in (hashicorp/terraform#30654). It is almost never intended, and nothing warns you at plan time.

    cidrsubnets allocates in order and never backtracks

    Each subnet starts at the next address aligned to its own size, so asking for a large block after several small ones can fail with space still free earlier in the range. Sort your newbits from largest block to smallest (smallest number first) if you run out.

    cidrsubnet or cidrsubnets?

    cidrsubnet gives one subnet and you choose its number, which keeps addresses stable when you add or remove subnets later. cidrsubnets gives a list and numbers them for you, packing different sizes without gaps — but inserting an entry in the middle shifts everything after it, and that is a rebuild of real infrastructure. For anything already deployed, prefer explicit netnum values.

    OpenTofu

    OpenTofu forked Terraform and carried these functions over, so the results apply there too. The vectors below come from the Go library that both build on, not from an OpenTofu binary.

    About this tool

    The address arithmetic is a TypeScript port of github.com/apparentlymart/go-cidr v1.1.1 — the library Terraform's CIDR functions are built on — together with Go's address formatting, including which run of zero groups in an IPv6 address collapses to ::. It is pinned by 72 golden vectors generated by running that library, and cross-checked against the examples in Terraform's function documentation. Error messages are reproduced from the same source rather than retyped; where this tool refuses a call that Terraform accepts but answers incorrectly, it says so instead of claiming to quote Terraform.

    One limit, stated rather than hidden: IPv4-mapped IPv6 prefixes ("::ffff:10.0.0.0/104") are rejected here. Terraform vendors an older address parser for those, and we could not verify its behaviour against the reference, so guessing seemed worse than declining. Everything runs in your browser; nothing is uploaded.