Skip to content

tfbridge panics on provider-produced MaxItems=1 state that Terraform accepts #3391

Description

@corymhall

What happened?

While investigating pulumi/pulumi-gcp#3666, we found a case where a Terraform provider can return state containing multiple values for a field whose schema is marked MaxItems: 1, and Terraform accepts that state, but pulumi-terraform-bridge panics while converting that Terraform state back into Pulumi outputs.

This issue is being filed as a behavior report. We do not yet know the right fix or whether the bridge should tolerate, normalize, or reject this kind of provider-produced state.

Terraform behavior

In this case, Terraform accepts provider-produced state where a nested computed field marked MaxItems: 1 contains multiple values.

A real Terraform state from the investigation contains:

boot_disk[0].initialize_params[0].resource_policies = [daily, weekly]

even though this field is modeled as MaxItems: 1 in the repro schema.

This suggests Terraform does not enforce MaxItems: 1 on provider-returned state in the same way it enforces it on config/input.

Pulumi behavior

tfbridge panics during output conversion with:

Unexpected multiple elements in array with MaxItems=1

The panic comes from the MaxItems=1 scalar projection logic in pkg/tfbridge/schema.go, where output conversion assumes any MaxItems=1 collection must have length 0 or 1 and fails otherwise.

Why this seems important

This means Pulumi is currently stricter than Terraform for provider-produced state in at least this scenario.

The concrete failure we observed is not in update request construction. The sequence is:

  1. Update runs.
  2. The provider finishes by reading state back.
  3. Read/flatten returns nested data where a computed MaxItems: 1 field contains multiple elements.
  4. tfbridge panics while converting that Terraform state to Pulumi outputs.

Reproducer

Draft PR with a focused repro test:

The targeted repro test is:

go test ./pkg/tests -run TestUpdateMaxItemsOneComputedNullStateParity -count=1 -v

It currently fails intentionally with the panic above.

Scope of the repro

The repro models:

  • description as the only user-visible update
  • boot_disk.source as ignored input
  • boot_disk.initialize_params.resource_policies as a nested computed MaxItems: 1 field
  • UpdateContext reusing ReadContext
  • a read/flatten step that returns multiple cloud policies only after update

This was derived from the GCP instance case, but the bridge behavior appears broader than that specific provider.

Related issue

  • pulumi/pulumi-gcp#3666

Open question

We are not proposing a fix direction yet.

The main open question is whether tfbridge should:

  • tolerate provider-produced output/state shapes that violate MaxItems: 1
  • normalize/recover such state before Pulumi projection
  • or continue treating this as invalid, in which case bridge/provider expectations likely need to be documented more clearly

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions