Skip to content

Mask only leaf paths in postgres update_mask - #6440

Open
denik wants to merge 3 commits into
mainfrom
denik/update-mask-leaf-only
Open

Mask only leaf paths in postgres update_mask#6440
denik wants to merge 3 commits into
mainfrom
denik/update-mask-leaf-only

Conversation

@denik

@denik denik commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

A bundle that changes a field nested inside a Lakebase message — say postgres_projects.default_endpoint_settings.autoscaling_limit_max_cu — cannot deploy at all when it declares no suspension field:

Field 'spec.default_endpoint_settings.suspension' is in update_mask but not provided in request

There were two helpers building update_mask from the plan's change paths, one that kept parent paths and one that dropped them, and the postgres resources were split between them. The one that keeps parents masks spec.default_endpoint_settings alongside the leaf, which asks the API to replace that message wholesale — and the API then requires the oneof groups directly beneath it to be populated in the body. A bundle only sends the fields it declares, so masking the parent can never be right for us. Keep the helper that drops parents.

postgres_projects/update_default_endpoint_autoscaling covers it and fails without the first commit, locally and on cloud.

The fake accepted the broken request, which is why nothing caught this. It now models the rule in exactly the three shapes probed against a real workspace on 2026-08-31:

mask body without a suspension field
spec.default_endpoint_settings rejected
spec (project, group two levels below) accepted
spec (endpoint, group one level below) accepted

So the rule is neither "every group under the mask" nor "every group one level under it". The fake reproduces only what was measured; widening it needs another probe.

update_default_endpoint_suspend still fails on the oneof group name — separate fix.

This pull request and its description were written by Isaac.

There were two helpers building update_mask from the plan's change paths, one
that kept parent paths and one that dropped them, and the postgres resources were
split between them. Keep the one that drops parents.

Masking a message asks the API to replace it wholesale, and the API then requires
every oneof group beneath that message to be populated in the request body.
Probed against a real workspace: update_mask=spec.default_endpoint_settings with
a body carrying only the autoscaling limits is rejected with "Field
'spec.default_endpoint_settings.suspension' is in update_mask but not provided in
request". A bundle only sends the fields it declares, so masking the parent can
never be right for us.

Co-authored-by: Isaac
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Approval status: pending

/acceptance/bundle/ - needs approval

8 files changed
Suggested: @pietern
Also eligible: @janniklasrose, @andrewnester, @shreyas-goenka, @anton-107, @lennartkats-db

/bundle/ - needs approval

4 files changed
Suggested: @pietern
Also eligible: @janniklasrose, @andrewnester, @shreyas-goenka, @anton-107, @lennartkats-db

General files (require maintainer)

Files: .nextchanges/bundles/postgres-leaf-update-mask.md, libs/testserver/postgres.go
Based on git history:

  • @pietern -- recent work in libs/testserver/, bundle/direct/dresources/

Any maintainer (@andrewnester, @anton-107, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db, @janniklasrose, @lennartkats-db, @rugpanov, @rclarey) can approve all areas.
See OWNERS for ownership rules.

Masking a nested message makes the API demand the oneof groups directly beneath it,
so a bundle that changes default_endpoint_settings.autoscaling_limit_max_cu without
declaring a suspension field could not deploy at all. The fake accepted it, which is
why nothing caught this.

Teach the fake the rule, in exactly the three shapes probed against a real workspace:
masking a nested message requires the groups below it, masking the top-level spec does
not, at either depth. The new test fails without the previous commit and passes with it,
locally and on cloud.

Co-authored-by: Isaac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant