Skip to content

Conversation

@twingate-blee
Copy link

Summary

Fixes a bug where arrays/lists were truncated to only the first element in the Go SDK during Read operations. This only affected the Go SDK - Python, TypeScript, and .NET SDKs worked correctly.

Fixes: #3240

Problem

When using Plugin Framework providers with ListNestedBlock or SetNestedBlock types, the Go SDK would:

  • ✅ Show all array elements after initial resource creation
  • ❌ Truncate arrays to 1 element after any update (which triggers a Read operation)
  • ✅ Work correctly in Python, TypeScript, and .NET SDKs

Example (Twingate provider)

Before fix:

{
  "inputs": {
    "accessServices": [2 elements],
    "accessGroups": [2 elements]
  },
  "outputs": {
    "accessServices": [1 element],  // ❌ Truncated!
    "accessGroups": [1 element]     // ❌ Truncated!
  }
}

After fix:

{
  "inputs": {
    "accessServices": [2 elements],
    "accessGroups": [2 elements]
  },
  "outputs": {
    "accessServices": [2 elements],  // ✅ Fixed!
    "accessGroups": [2 elements]     // ✅ Fixed!
  }
}

Root Cause

The bug occurred in two places in pkg/convert/flattened.go:

  1. flattenedEncoder.fromPropertyValue() (lines 29-58): Only handled single elements, not arrays. When encoding multi-element arrays, only the first element was sent to the Terraform provider.

  2. flattenedDecoder.toPropertyValue() (lines 58-74): Returned an error when receiving >1 elements. This error was swallowed somewhere in the chain, causing only the first element to be preserved in Go SDK outputs.

These encoders/decoders are selected when IsMaxItemsOne() incorrectly identifies a multi-item list as single-item. This commonly occurs with Plugin Framework providers using ListNestedBlock or SetNestedBlock.

The Fix

Encoder Fix

  • Checks if input is an array using v.IsArray()
  • If so, encodes all elements and returns them as a list
  • Maintains backward compatibility for legitimate single-item inputs

Decoder Fix

  • When list has >1 elements, decodes all into an array
  • Returns as resource.NewArrayProperty(values) instead of erroring
  • Maintains backward compatibility for 0 or 1 element cases

Testing

Tested with the Twingate Pulumi provider, which uses Plugin Framework ListNestedBlock types:

Test Results

Before fix:

  • ✅ Initial create: Arrays show all elements (2)
  • ❌ After update (triggers Read): Arrays truncated to 1 element
  • ✅ Only affected Go SDK; Python/TypeScript/.NET worked correctly

After fix:

  • ✅ Create operations: All elements preserved
  • ✅ Update operations: All elements preserved
  • ✅ Read/refresh operations: All elements preserved
  • ✅ Works for both types.List and types.Set
  • ✅ Works for both ListNestedBlock and SetNestedBlock
  • ✅ Independent arrays remain independent

@guineveresaenger
Copy link
Contributor

Hi @twingate-blee - thank you for opening this pull request. Let me run tests for you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Go SDK Truncates Arrays to First Element During Read Operations

3 participants