Skip to content

service_splitter: nil pointer dereference when RequestHeaders and ResponseHeaders are null #482

@charlie-collard

Description

@charlie-collard

The consul_config_entry_service_splitter resource crashes with a nil pointer dereference when the service splitter is updated outside of Terraform (e.g., via Consul CLI/API) in a way that removes the RequestHeaders and ResponseHeaders fields.

These fields are set to {} on creation by the provider, but they are optional and may be null if the resource is modified by non-Terraform sources.

I have reproduced this on the latest version v2.23.0

Reproduction

Terraform config

terraform {
  required_providers {
    consul = {
      source  = "hashicorp/consul"
      version = "2.23.0"
    }
  }
}

provider "consul" {
  address = "https://your-consul-server.example.com"
}

resource "consul_config_entry_service_defaults" "main" {
  name     = "bug-repro"
  protocol = "http"
  expose { checks = false }
}

resource "consul_config_entry_service_defaults" "canary" {
  name     = "bug-repro-canary"
  protocol = "http"
  expose { checks = false }
}

resource "consul_config_entry_service_splitter" "test" {
  name = "bug-repro"

  splits {
    weight  = 100
    service = "bug-repro"
  }

  splits {
    weight  = 0
    service = "bug-repro-canary"
  }

  depends_on = [
    consul_config_entry_service_defaults.main,
    consul_config_entry_service_defaults.canary
  ]
}

Steps to reproduce

# Create splitter via Terraform
terraform apply -auto-approve

# Verify RequestHeaders and ResponseHeaders are non-null in Consul
consul config read -kind service-splitter -name bug-repro

# Update via Consul CLI (common for adjusting canary weights)
consul config write - <<EOF
Kind = "service-splitter"
Name = "bug-repro"
Splits = [
  { Weight = 90, Service = "bug-repro" },
  { Weight = 10, Service = "bug-repro-canary" }
]
EOF

# Verify RequestHeaders and ResponseHeaders are now null in Consul
consul config read -kind service-splitter -name bug-repro

# Trigger refresh - crashes
terraform plan

Expected Behavior

Terraform should handle null header fields gracefully during refresh.

Actual Behavior

Provider crashes with nil pointer dereference:

  Stack trace from the terraform-provider-consul_v2.23.0_x4 plugin:
11:16:16   
11:16:16   panic: runtime error: invalid memory address or nil pointer dereference
11:16:16   [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0xb4d4a4]
11:16:16   
11:16:16   goroutine 1822 [running]:
11:16:16   github.com/hashicorp/terraform-provider-consul/consul.(*serviceSplitter).Write.func1(0x0, {0xee9ddb, 0xf})
11:16:16     github.com/hashicorp/terraform-provider-consul/consul/resource_consul_config_entry_service_splitter.go:239 +0x144
11:16:16   github.com/hashicorp/terraform-provider-consul/consul.(*serviceSplitter).Write(0x40001a2a10?, {0x11d9e50?, 0x40001a2e70?}, 0x40001a2a10, 0x40009d2f60)
11:16:16     github.com/hashicorp/terraform-provider-consul/consul/resource_consul_config_entry_service_splitter.go:263 +0x4a8
11:16:16   github.com/hashicorp/terraform-provider-consul/consul.resourceFromConfigEntryImplementation.configEntryImplementationRead.func4(0x40001a2a10, {0xce79c0?, 0x40004b60e0?})
11:16:16     github.com/hashicorp/terraform-provider-consul/consul/resource_consul_config_entry_concrete.go:111 +0x110
11:16:16   github.com/hashicorp/terraform-plugin-sdk/helper/schema.(*Resource).RefreshWithoutUpgrade(0x4000452320, 0x4000a38500, {0xce79c0, 0x40004b60e0})
11:16:16     github.com/hashicorp/terraform-plugin-sdk@v1.17.2/helper/schema/resource.go:470 +0x224
11:16:16   github.com/hashicorp/terraform-plugin-sdk/internal/helper/plugin.(*GRPCProviderServer).ReadResource(0x400007a200, {0x40005943c0?, 0x4000994a38?}, 0x40005943c0)
11:16:16     github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/helper/plugin/grpc_provider.go:535 +0x2b4
11:16:16   github.com/hashicorp/terraform-plugin-sdk/internal/tfplugin5._Provider_ReadResource_Handler({0xe90120, 0x400007a200}, {0x11d5158, 0x4000a033e0}, 0x40001a24d0, 0x0)
11:16:16     github.com/hashicorp/terraform-plugin-sdk@v1.17.2/internal/tfplugin5/tfplugin5.pb.go:3269 +0x1b8
11:16:16   google.golang.org/grpc.(*Server).processUnaryRPC(0x4000194b40, {0x11dc2c0, 0x400045c9c0}, 0x4000a33200, 0x4000459470, 0x1b98c90, 0x0)
11:16:16     google.golang.org/grpc@v1.56.3/server.go:1335 +0xaf4
11:16:16   google.golang.org/grpc.(*Server).handleStream(0x4000194b40, {0x11dc2c0, 0x400045c9c0}, 0x4000a33200, 0x0)
11:16:16     google.golang.org/grpc@v1.56.3/server.go:1712 +0x720
11:16:16   google.golang.org/grpc.(*Server).serveStreams.func1.1()
11:16:16     google.golang.org/grpc@v1.56.3/server.go:947 +0xa0
11:16:16   created by google.golang.org/grpc.(*Server).serveStreams.func1 in goroutine 26
11:16:16     google.golang.org/grpc@v1.56.3/server.go:958 +0x12c
11:16:16   
11:16:16   Error: The terraform-provider-consul_v2.23.0_x4 plugin crashed!

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