postgres: fix deploy failing with unknown field path in update_mask - #6374
Draft
denik wants to merge 1 commit into
Draft
postgres: fix deploy failing with unknown field path in update_mask#6374denik wants to merge 1 commit into
denik wants to merge 1 commit into
Conversation
Deploying a postgres_project whose custom_tags carry a value that changes
each deploy failed with
400 INVALID_PARAMETER_VALUE
Unknown field path in update_mask: 'spec.custom_tags[0].value'
The mask was built from the plan's change list, which addresses a list
element by index. The API only accepts the whole repeated field.
Probing the API shows a static list or "*" does not work either: the
backend expands the mask to leaves and requires every masked leaf to be
populated in the request body, which a bundle that omits optional fields
never is. Two more paths differ from the field name: members of a oneof
are masked under the group name (spec.expiration, spec.suspension), and
immutable fields have no path at all.
So each resource gets a static map from spec field path to accepted mask
path, and the mask is derived from the request body so the two always
agree. All five postgres resources shared the bug.
Co-authored-by: Isaac
Contributor
Approval status: pending
|
denik
marked this pull request as draft
August 25, 2026 09:24
Collaborator
Integration test reportCommit: aa81513
13 interesting tests: 8 flaky, 4 SKIP, 1 RECOVERED
Top 6 slowest tests (at least 2 minutes):
|
denik
added a commit
that referenced
this pull request
Aug 25, 2026
The direct engine now sends the PATCH, and the real API rejects the mask path it builds: suspend_timeout_duration is a oneof member, so the API only accepts the group name spec.suspension. Separate bug, separate fix (#6374). The testserver ignores update_mask, which is why the local run is unaffected. Co-authored-by: Isaac
denik
added a commit
that referenced
this pull request
Aug 25, 2026
The direct engine now sends the PATCH, and the API rejects the mask path it builds: suspend_timeout_duration is a member of the suspension oneof, so only the group name spec.suspension is accepted. Separate bug, separate fix (#6374). Teach the testserver to validate update_mask against the paths the real API accepts, so the failure reproduces locally rather than only on aws. The engines diverge from the second deploy on, so those steps go back to per-engine files, and the deploy requests are recorded per engine: same body, different mask. Cloud stays enabled, with the golden recording what the real workspace does. Co-authored-by: Isaac
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.
Why
Deploying a
postgres_projectwhosecustom_tagscarry a value that changes each deploy failed withUnknown field path in update_mask: 'spec.custom_tags[0].value'. The mask came from the plan's change list, which addresses a list element by index; the API only accepts the whole repeated field. Reported by a customer.Changes
Each postgres resource gets a static map from spec field path to the mask path the API accepts, and the mask is derived from the request body so the two always agree. Probing the API showed that neither
*nor a static list works: the backend expands the mask to leaves and requires every masked leaf to be populated in the request, which a bundle that omits optional fields never is. Two more paths differ from the field name — members of a oneof are masked under the group name (spec.expiration,spec.suspension), and immutable fields have no path at all. All five postgres resources shared the bug.Tests
New acceptance test
postgres_projects/update_custom_tagsreproduces the failure and asserts the tag value the API actually applied.TestPostgresSpecUpdateMaskswalks each spec with reflection, so a new SDK field fails the test until it has a mask entry. The fake server now rejects an indexed mask path like the real API does. Ran the whole postgres suite against a real AWS workspace.Updates to a duration or timestamp field (
spec.suspension,spec.expiration) are not covered: structdiff seesduration.Durationandtypes/time.Timeas always equal because each wraps a single unexported protobuf pointer, so the direct engine never plans an update for them. Separate bug, separate fix.