fix: vault_update_properties treats null as property deletion - #88
Conversation
Passing { key: null } previously serialized a literal 'null' into
frontmatter with no way to remove a property at all. A null value now
deletes the key, in both updateProperties and vault_write_note's
frontmatter merge (shared mergeFrontmatter helper in frontmatter.ts).
Nulls already present in existing frontmatter (Obsidian empty
properties like 'due:') are preserved — only the caller's nulls are
deletions — and nullStr: '' makes them round-trip Obsidian-style as
'due:' instead of 'due: null'. Deleting the last property removes the
frontmatter block entirely.
destructiveHint flips to true on vault_update_properties: the tool can
now irreversibly remove data.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis PR implements null-value property deletion for vault notes. A new ChangesNote Property Null-Deletion Semantics
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
vault_update_propertieswas merge-only with no property-removal path. Passing{ "key": null }carried the null straight through the spread merge into the YAML serializer, which wrote a literalkey: nullinto frontmatter. Hit live 2026-06-10 cleaning a stray property off a note — recovery required a manual file edit.Fix
Contract: null means delete. A key explicitly set to
nullin the update is removed from frontmatter.mergeFrontmatterhelper infrontmatter.ts— used by both merge paths (updatePropertiesandvault_write_note'sserializeNote, including its new-file branch) so the contract is consistent everywhere.due:parse as null — are preserved when unmentioned; filtering all nulls would silently strip empty template properties on every update.nullStr: ""added to the YAML stringify options so preserved nulls round-trip Obsidian-style asdue:instead ofdue: null.---stub).describe()document the contract on both tools.vault_update_propertiesannotations changedestructiveHint: false → true— the tool can now irreversibly remove data (and already overwrote values). Some MCP clients may start gating it behind a confirmation prompt; this is intended. Moved fromADDITIVE_WRITE_TOOLStoDESTRUCTIVE_TOOLSin the annotation tests (vault_update_memoryremains the only genuinely additive writer).Tests
9 new tests, all byte-exact content assertions. Mutation-audited:
529 tests pass; lint, build, prettier clean.
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
nullnow correctly deletes that key from notes while preserving unmodified properties.Documentation