terraform plan fails on a GCP budget: amount validation error - specified_amount and last_period_amount are both set
Fixes the Terraform error when a google_billing_budget sets both specified_amount and last_period_amount. Covers the budget_amount block rule, choosing one amount type, and validating the plan. Use when plan fails on budget amount validation. Not for IAM or API errors.
TL;DR
A GCP budget can use exactly one amount type: either a fixed specified_amount or a last_period_amount that tracks the previous period. You set both, and the provider refuses. Remove one of the two blocks and the plan will validate.
Use this when
terraform planfails ongoogle_billing_budgetwith an amount validation error.- The
budget_amountblock contains bothspecified_amountandlast_period_amount. - A module you consume recently added one of the two blocks.
Not for this skill when
- The plan fails on billing account permissions. That is an IAM problem.
- The budget applies but alerts misbehave. That is a threshold or filter problem.
Steps
- Open the
google_billing_budgetresource and find theamountblock. Verify: bothspecified_amountandlast_period_amountare present. - Decide which one you want. Fixed number: keep
specified_amountwith aunitsvalue like"1000". Track-last-period: keeplast_period_amountalone. Verify: only one block remains. - Run
terraform validatethenterraform plan. Verify: the amount validation error is gone. - If a shared module sets one of them, override or fork the module rather than fighting it per resource. Verify: the plan shows a single amount block in the rendered config.
- Apply and confirm the budget in the GCP console shows the intended amount type. Verify: the console's budget detail matches your choice.
lastperiodamount gotcha
With last_period_amount, the budget amount changes every period, which can surprise alerting. Verify: your alert thresholds make sense against a moving amount.
Compatibility: Terraform Google provider 4.x and later, google_billing_budget resource.
Why it happens
The provider mirrors the API's one-of constraint: the budget amount is a union type. HCL lets you write both blocks without a syntax error, so the mistake surfaces only at validation time.
Edge cases / pitfalls
unitsinsidespecified_amountis a string like"500", not a number. A bare number can fail a different validation.- Imported budgets sometimes render with both blocks in state. Clean the config, not the state.
- The same one-of rule applies in the raw REST API, so this is not a provider quirk.
- Currency follows the billing account; you do not set it on the budget.
Provenance
Resolved from the public thread: https://vectle.com/posts/pstv73F92KSTQKCQvvSz75wQ