Hello everyone!
I am currently writing a small custom provider for my thesis project, and I ran into problems
the provider is supposed to create a simple resource on a local running Bitbucket.
I studied the Terraform guides about writing providers and some existing providers to understand how Terraform interacts with providers and golang itself.
I got it working, somewhat - but I run into the same problem not matter what I do. When I try to create a resource using my custom providers, this error pops up:
When applying changes to customResource, provider
ācustomProviderā produced an unexpected new value: Root resource
was present, but now absent.
Sadly, this error almost never comes up in the entire internet - I looked into it all day. As I understand it, the āinconsistent result after applyā error is the result of the provider changing ResourceData in a way that isnāt nessecary, so Terraform thinks a change has been made? I donāt undertand what āRoot resourceā refers to in this context, though.
I think the problem stems from the fact that the id of my object is an int (server-side), but Terraform forces me to use TypeString - or because it is a Computed value, or a combination of both. I convert the id into string in the resourceSomethingRead-function, of course. My logs indicate that the entire create and read operation runs into no problems: the response from the server is accepted with correct codes and all content is parsed correctly, too. But still, the error is thrown.
I looked into this all day and wasnāt able to find any answers or pointer to understanding Root resource correctly, or how the read-function works and when it is called by Terraform. I think the problem lies somewhere in there.
Did anyone ever run into similar problems, or does someone understand what the problem is? Does anyone know a provider that successfully maps an external non-string ID into Terraform?
For context, here is the full content of my relevant provider files (its really simple, or should be):
resource_project.go
provider.go
client.go
Some more context: this is what a successful POST to the server returns, the POST body contains all information but the ID (because it is exclusively computed by the server and canāt be set manually)
A colleague of mine was able to spot the problem - the fix was actually fairly simple.
In code, i used tried to set the Id field of the ResourceData like this:
d.set("id", idString)
Id is however an inherent field of ResourceData, so there is an actual setter for it, obviously
d.setId(idString)
that small mistake causes Terraform to not see the resulting object, because the id is never set, but the id also is the main identifier of the object. Such a small oversight! Itās always the smallest things. My IDE doesnāt understand import via Git-tags, so I couldnāt figure it out that way either. Oh well, maybe it will help someone else!
1 Like
Hi @naumannt! Iām sorry you ran into this confusing message, and Iām glad you were able to figure it out.
As you learned, the current SDK considers id
to be a special attribute because the absense of an id
is how the provider tells the SDK that an object has been deleted. In your case then, the SDK saw that your ācreateā function didnāt call SetId
and assumed you meant that the operation had ended with no object being created. Terraform Core then complained about that result, because the absence of an object after apply disagreed with the earlier plan to create the object.
Generally-speaking, Terraform Core expects that the final result after calling the apply operation (which the SDK itself splits into separate āCreateā, āUpdateā, āDeleteā functions) will match the values shown in the plan and will reject the result if not, because values other than what were planned would otherwise cascade into the configurations for other resources and cause them to produce a result other than what was planned, which would then be hard to diagnose due to the effect being so far from the cause.
The current SDK abstracts these details away quite a bit though, including automatically generating the plan for you in most cases and this funny behavior with SetId
, which in this case unfortunately led to the error message being pretty unhelpful because Terraform Core was reporting the error using its own lower-level view of things, rather than the SDKās higher-level view of things. 
In any event, Iām glad you figured it out, and Iām sorry it wasnāt easier to understand what was going on here. The team that works on the plugin SDK is currently working on a new iteration of the API which aims to align better the SDK abstractions with Terraform Coreās assumptions, so hopefully this confusing trap will be addressed by that work.
Naumannt, Thank you so much for this. This one had me stumped too. I guess one doesnāt appreciate good error message and handling until you come across an issue like this.
Again, many thanks 