fix(resource): serialize only writable fields in update payloads#97
Merged
Conversation
Update payloads carried every hydrated field: read-only top-level metadata (created_time serialized as a date object, created_by, url), computed property values the API refuses (formula, rollup, created/edited metadata, unique_id), and null-valued properties serialized as empty arrays. Any of these fails validation, so updating a retrieved page, database row, or database never worked against the live API on any version. toArrayForUpdate() is now strict on the accepted keys — subsuming the earlier object/id and null icon/cover handling — and pages drop computed property values and properties whose serialized form carries no value. Explicitly set values, including false, still serialize.
Serialization snake_cases array keys including property names, so the filter's lookups by original name missed camelCase-named properties and the reviewer-found leak persisted for them. The filter now derives the serialized key with the same transform, and the tests assert the transformed names so they can no longer pass vacuously.
This was referenced Jul 14, 2026
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.
Description
Fixes retrieve-then-update, which never worked against the live API on any version: update payloads carried every hydrated field, and the API rejects several of them.
toArrayForUpdate()onPage,Database, andDataSourceis now strict on the accepted update keys, instead of force-including them alongside every other non-empty field. This stops read-only top-level metadata leaking into bodies —created_time(which serialized as a date object and always failed validation),created_by,last_edited_*,url,parent— and subsumes the earlierobject/idand nullicon/coverspecial-casing.created_by,created_time,last_edited_by,last_edited_time,formula,rollup,unique_id—verificationstays, being writable on wiki pages) and properties hydrated with a null value, whose serialized form carries no usable value ("date": nullbecame"date": []). The filter resolves property names through the same snake_case key transform serialization applies, so camelCase-named properties are covered.false(archived,is_locked) and0; thearchived: falseround-trip behavior from Page object serializes archived: false on create and update, causing Notion API validation error #67 is preserved and still pinned.Motivation and context
The natural "retrieve, mutate, update" flow failed with confusing validation errors on any real-world page (anything with computed or empty properties) — for example
body.properties.Last edited by.title should be definedorbody.created_time should be a string.How has this been tested?
archived: falseassertion intact.2022-06-28and2026-03-11), a database row with a full property set, and a database — all of which failed before the change.parallel-lint,phpcs, PHPStan, and Psalm.Known remaining edge (separate issue): a data source schema round-trip still fails on computed property configurations, and camelCase-named properties are renamed by the payload key transform — both pre-existing and tracked separately.
Types of changes
PR checklist