Terraform Version Constraint Parser

Get the actual range a constraint allows. The one worth checking is ~>, where two components and three components mean different things and both look equally deliberate.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Parse. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A minor-freedom constraint

Two components, so the minor may move and the next major cannot arrive

"~> 5.0"

No upper bound

Satisfied by any future major, so a breaking release can land with no change from you

">= 1.5.0"

A set nothing satisfies

Init fails every run, and the message sounds like a missing version in the registry

">= 2.0.0, < 1.0.0"

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Writing ~> 5.2.0 when you meant to allow minor releases

    Three components pins the minor. 5.3.0 is excluded, so a minor release with a fix you want never arrives and the constraint looks like it should allow it.

    Instead:Write ~> 5.2 for minor freedom, and ~> 5.2.0 only when you genuinely want patches only.

  2. Leaving a provider constraint open-ended

    A major release can remove arguments, and with no upper bound the next init picks it up. Nothing in your repository changed, so the break is not attributable to any commit.

    Instead:Use ~> with two components. It allows everything useful and excludes the next major.

  3. Pinning a provider to an exact patch version

    The lock file already records the exact version, so the constraint adds nothing except blocking provider bug fixes.

    Instead:Constrain with ~> and let .terraform.lock.hcl hold the exact version. Commit the lock file.

~> 1.2 and ~> 1.2.0 are not the same constraint

The pessimistic operator lets the rightmost component you wrote increment. How much freedom that gives depends entirely on how many components you wrote, which is why two constraints that look alike behave differently.

Two components lets the minor move

~> 5.0 means at least 5.0.0 and less than 6.0.0. The minor is the rightmost component, so 5.1, 5.31 and 5.99 are all allowed and 6.0.0 is not. This is what most people want from a provider: bug fixes and new resources arrive, and a major cannot land without an edit.

Three components lets only the patch move

~> 5.2.0 means at least 5.2.0 and less than 5.3.0. Now the patch is the rightmost component, so 5.3.0 is excluded. That is a much tighter pin than it looks, and a minor release carrying a fix you need will not be picked up until somebody changes this line.

No upper bound means a major can arrive on its own

>= 1.5.0 is satisfied by 2.0.0 and by 9.0.0. A provider major is allowed to remove arguments, and a core major has removed syntax before. Because nothing changed in your repository, the failure lands on whoever runs init next and looks like their problem.

An exact pin is right for core and usually wrong for a provider

For a provider, .terraform.lock.hcl already records the exact version, so pinning the constraint too just stops patch fixes. For required_version an exact pin means every person and every pipeline must match, which is defensible when a container image or a .terraform-version file guarantees it and a support burden otherwise.

A contradiction reads like a registry problem

>= 2.0.0, < 1.0.0 admits nothing. Terraform reports that it could not find a matching version, which sounds like the registry is missing something rather than like the constraint being impossible. Bounds that merely touch, such as >= 2.0.0, < 2.0.0, fail the same way.

A prerelease is never matched by a range

1.0.0-beta1 is only selected by an exact constraint. So >= 1.0.0-beta1 will not pick up beta2, and once the final release exists it is not what you get either. Pin exactly while you need a prerelease, and move off it when there is a release.