fix: a nested attribute is held as a value that can be unknown - #115
Merged
Conversation
Every generated resource failed at apply. A nested attribute's model field was the generated struct — a pointer for an object, a slice for a list — and neither can represent unknown, which is what a Computed attribute carries in the plan before the API has answered: Received unknown value, however the target type cannot handle unknown values. Path: links Target Type: *CredentialLinksModel The field is now types.Object or types.List, and each nested struct gains an AttrTypes function beside it naming the object type it maps onto. State building goes through ObjectValueFrom and ListValueFrom, so the mappers return diagnostics; construction decodes the plan value with As and ElementsAs before reading its fields; and the conditional validators test absence with IsNull, which now applies to every attribute alike. Found by running the generated acceptance tests against a live tenant. The provider built, vetted and passed 213 unit tests in that state, and could not apply a single resource. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The first live audit run panicked before its first request. A singleton is classified a resource without a create operation — it is written through its update call — so the create slot is empty and deriving its plan dereferenced nil. It is now refused with a reason, and the rest of the run stands: an entity the audit cannot exercise is a fact about that entity. The test pins the shape that crashed rather than the line that fixed it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found by running the generated acceptance tests against a live ThousandEyes tenant. Every one of the 35 generated resources failed at apply, all with the same error. The provider built, vetted, passed 213 unit tests and regenerated byte-identical in that state.
Cause
A nested attribute's model field was the generated struct —
*XxxModelfor an object,[]XxxModelfor a list. Neither can represent unknown, which is exactly what a Computed attribute carries in the plan before the API has answered.linksandcoordinatesare server-returned HATEOAS blocks, so they are Computed on every resource that has one.Scale: 240 such fields in ThousandEyes, 959 in GitHub, plus 29 computed
ListNestedAttributes carrying the same latent fault.Fix
*XxxModeltypes.Object[]XxxModeltypes.ListXxxModelAttrTypes()beside each nested structObjectValueFrom/ListValueFromAs/ElementsAsinto the struct, then read== nil.IsNull()The mappers now return
diag.Diagnostics, because building an object can report a mismatch against its declared types. The nested structs are still generated — they are what the object is built from and decoded back into.The curated fixture caught something I had wrong: I had concluded from both pilots that nested objects are read-only and construction needed no change. That was true only because binding had pruned every writable nested object in those two documents. The fixture has writable ones, and
construct.gofailed to compile until it decoded throughAs/ElementsAs.Also here
internal/audit/planpanicked with a nil dereference before its first request, on the same live run. A singleton is classified a resource but has no create operation — it is written through its update call — so the create slot is empty. It is now refused with a reason, and the rest of the run stands.Verification
Both pilots regenerate byte-identical and pass postcheck (
go mod tidy,build,vet):Live re-run against the tenant: the conversion error is gone — 0 occurrences, down from 35. The provider now reaches the API, and fails there instead (HTTP 400 on create), which is a different and later problem: the generated fixtures do not yet satisfy what the API requires.
🤖 Generated with Claude Code