Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provider produced invalid plan error when planning certain high-precision floating point numbers #1017

Open
SBGoods opened this issue Jul 8, 2024 · 0 comments
Labels
bug Something isn't working types Issues and pull requests about our types abstraction and implementations.

Comments

@SBGoods
Copy link
Contributor

SBGoods commented Jul 8, 2024

Problem Statement

When round-tripping certain floating point numbers such as MaxFloat32 from Terraform config to a type.Float32 or a type.Float64 framework type:

resource "framework_float64_precision" "test" {  
    float64_attribute = 340282346638528859811704183484516925440
}

Applying the above config results in the following error from Terraform:

╷
│ Error: Provider produced invalid plan
│ 
│ Provider "registry.terraform.io/hashicorp/scaffolding" planned an invalid value for scaffolding_float32_precision.test.float32_attribute: planned value
│ cty.NumberIntVal(3.4028234663852886e+38) does not match config value cty.NumberIntVal(3.4028234663852885981170418348451692544e+38).
│ 
│ This is a bug in the provider, which should be reported in the provider's own issue tracker.
╵

Context:

Floating point numbers in Terraform configuration are parsed in Terraform core as strings with 512 bit precision into a big.Float object. Most floating point numbers that are roundtripped in the framework into either a type.Float32Value or a type.Float64Value via a float32 or float64 conversion will introduce some accuracy loss in the floating point value.

Floating point numbers are compared using (big.Float).Cmp() in the framework and in terraform-plugin-go but when Terraform core compares numbers to ensure value consistency, it uses it's JSON string representation. Essentially, two numbers are considered the same in Terraform core only when they write the same JSON.

There are a certain subset of numbers where a conversion from the 512-bit precision big.Float object to either a float64 or float32 value does not result in any accuracy loss (they have the exact same binary representation). These numbers will be considered equal when compared using (big.Float).Cmp() but will write different JSON strings such that Terraform core will consider them different numbers.

The number has to meet the following conditions to run into this error (first two points from https://stackoverflow.com/a/67145511):

  • The number must be rational (can be expressed as a fraction of integers)
  • The denominator of such fraction must be a power of two (1, 2, 4, 8, etc.)
  • The number in Terraform config must must write to JSON with more precision than it's float64/float32 equivalent

This issue affects both types.Float32 and types.Float64

Potential Solutions:

To fix this issue, we would likely need to change the number comparison logic in both the framework and terraform-plugin-go to ensure that the 512-bit precision big.Float object is sent to Terraform core during the ReadResource, ReadDatasource and ApplyResourceChange RPCs as well as modifying the logic during PlanResourceChange RPC to send the correct value during planning

@SBGoods SBGoods added bug Something isn't working types Issues and pull requests about our types abstraction and implementations. labels Jul 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working types Issues and pull requests about our types abstraction and implementations.
Projects
None yet
Development

No branches or pull requests

1 participant