Today I looked into upgrading Mastercard/restapi terraform provider from v2.0.1 to v.3.0.0 in our project. This failed with the following error message:
╷
│ Error: Invalid JSON String Value
│
│ with restapi_object.bootstrap-indices,
│ on resources-index.tf line 36, in resource "restapi_object" "bootstrap-indices":
│ 36: read_data = ""
│
│ A string value was provided that is not valid JSON string format (RFC 7159).
│
│ Given Value:
│
╵
╷
│ Error: Invalid JSON String Value
│
│ with restapi_object.bootstrap-indices,
│ on resources-index.tf line 59, in resource "restapi_object" "bootstrap-indices":
│ 59: destroy_data = ""
│
│ A string value was provided that is not valid JSON string format (RFC 7159).
│
│ Given Value:
│
╵
The use case we use this terraform provider for is related to bootstrap Elasticsearch indices, which get rotated automatically later on (by an Elasticsearch feature called index lifecycle policies). This is currently not supported by the official elasticstack terraform provider.
For this special use case we only care about creation and deletion of indices. In order to make read work, we read all the indices matching the respective pattern (using wild cards) and we ignore all the drift (ignore_all_server_changes = true). This worked flawlessly in the past (using v2.0.1 of the provider).
The config we used successfully with v2.0.1 looks like this:
locals {
bootstrap_indices = toset([
"some_index_name",
])
}
resource "restapi_object" "bootstrap-indices" {
for_each = local.bootstrap_indices
path = "/"
data = jsonencode({
aliases = {
"${each.key}" = {
is_write_index = true,
},
},
})
object_id = each.key
ignore_all_server_changes = true
debug = true
read_method = "GET"
read_path = "/{id}-*"
read_data = ""
create_method = "PUT"
# encoded form of: /<{id}-{now/d}-000001>
# {id} is replaced by the terraform provider, the rest is Elasticsearch date math:
# https://www.elastic.co/docs/reference/elasticsearch/rest-apis/api-conventions
create_path = "/%3C{id}-%7Bnow%2Fd%7D-000001%3E"
# NOTE: This is just a placeholder operation, that is compatible with both
# Elasticsearch and Mastercard/restapi Terraform provider.
# We need this, since we do not want to perform any change in the case of
# an update.
update_method = "POST"
update_path = "/{id}/_validate/query"
update_data = jsonencode({
query = {}
})
# IMPORTANT: We use wildcards for delete, so all the indices for the given alias/prefix
# are removed. This is necessary to allow destroy for index lifecycle policies (ILM),
# since ILM are not deletable as long as they are still referenced by indices.
destroy_method = "DELETE"
destroy_path = "/{id}-*"
destroy_data = ""
lifecycle {
prevent_destroy = true
}
}
With the above configuration, the validation fails immediately, since "" is not considered valid JSON for read_data and update_data. So I tried several approaches like read_data = null, read_data = jsonencode(null), read_data = jsonencode({}). While these pass the validation of the config, terraform plan still fails. Based on the log files, it looks to me, that the reason for this is the current value in the terraform state, which is not valid json and therefore unmarshal for this value fails. This prevents the smooth migration from v2.0.1 to v3.0.0 for us.
Snippets from the debug logs with jsonencode({}) as value
2026-06-12T16:32:40.491+0200 [ERROR] provider.terraform-provider-restapi_v3.0.0: Response contains error diagnostic: tf_provider_addr=github.com/Mastercard/terraform-provider-restapi tf_rpc=ReadResource @caller=github.com/hashicorp/terraform-plugin-go@v0.29.0/tfprotov6/internal/diag/diagnostics.go:58 @module=sdk.proto diagnostic_attribute="AttributeName(\"destroy_data\")" diagnostic_summary="Invalid JSON String Value" tf_proto_version=6.10 tf_req_id=c6e7fe2d-b0f1-e48b-9611-b8a1fc65fc79 tf_resource_type=restapi_object
diagnostic_detail=
| A string value was provided that is not valid JSON string format (RFC 7159).
|
| Given Value:
diagnostic_severity=ERROR timestamp="2026-06-12T16:32:40.491+0200"
2026-06-12T16:38:39.046+0200 [ERROR] provider.terraform-provider-restapi_v3.0.0: Response contains error diagnostic: tf_rpc=ReadResource @module=sdk.proto diagnostic_attribute="AttributeName(\"destroy_data\")"
diagnostic_detail=
| A string value was provided that is not valid JSON string format (RFC 7159).
|
| Given Value:
diagnostic_summary="Invalid JSON String Value" tf_proto_version=6.10 tf_provider_addr=github.com/Mastercard/terraform-provider-restapi @caller=github.com/hashicorp/terraform-plugin-go@v0.29.0/tfprotov6/inte
rnal/diag/diagnostics.go:58 diagnostic_severity=ERROR tf_req_id=6878ae9f-0808-ca0a-284e-e8f030e30eb2 tf_resource_type=restapi_object timestamp="2026-06-12T16:38:39.046+0200"
2026-06-12T16:38:39.047+0200 [ERROR] vertex "restapi_object.bootstrap-indices[\"some_index_name\"]" error: Invalid JSON String Value
2026-06-12T16:38:39.047+0200 [ERROR] vertex "restapi_object.bootstrap-indices (expand)" error: Invalid JSON String Value
╷
│ Error: Invalid JSON String Value
│
│ with restapi_object.bootstrap-indices["some_index_name"],
│ on resources-index.tf line 59, in resource "restapi_object" "bootstrap-indices":
│ 59: destroy_data = jsonencode({})
│
│ A string value was provided that is not valid JSON string format (RFC 7159).
│
│ Given Value:
│
╵
Today I looked into upgrading
Mastercard/restapiterraform provider from v2.0.1 to v.3.0.0 in our project. This failed with the following error message:The use case we use this terraform provider for is related to bootstrap Elasticsearch indices, which get rotated automatically later on (by an Elasticsearch feature called index lifecycle policies). This is currently not supported by the official elasticstack terraform provider.
For this special use case we only care about creation and deletion of indices. In order to make read work, we read all the indices matching the respective pattern (using wild cards) and we ignore all the drift (
ignore_all_server_changes = true). This worked flawlessly in the past (using v2.0.1 of the provider).The config we used successfully with v2.0.1 looks like this:
With the above configuration, the validation fails immediately, since
""is not considered valid JSON forread_dataandupdate_data. So I tried several approaches likeread_data = null,read_data = jsonencode(null),read_data = jsonencode({}). While these pass the validation of the config,terraform planstill fails. Based on the log files, it looks to me, that the reason for this is the current value in the terraform state, which is not valid json and therefore unmarshal for this value fails. This prevents the smooth migration from v2.0.1 to v3.0.0 for us.Snippets from the debug logs with
jsonencode({})as value