makeplane / makeplane/plane-python-sdk

[bug]: update() strips None values via exclude_none=True, making it impossible to clear nullable fields

Open
#35 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
17
Forks
24
Avg merge
8d 9h
Merged PRs (30d)
2

Description

Summary

The update() method on every resource class strips None values from the payload via model_dump(exclude_none=True),
making it impossible to clear any nullable field on an existing work item (or any other resource using the same
pattern).

Reproducer

# Setup: work item with target_date = "2026-05-17"
data = UpdateWorkItem(target_date=None)
client.work_items.update(
    workspace_slug=ws, project_id=p, work_item_id=w, data=data, 
) 
# Expected: target_date cleared to null
# Actual: silent no-op — target_date still 2026-05-17
# Wire body sent: {} (None stripped by exclude_none=True)

Root cause

plane/api/work_items/base.py line 102 (same pattern in other resources):

response = self._patch(
    f"{workspace_slug}/projects/{project_id}/work-items/{work_item_id}",
    data.model_dump(exclude_none=True),
)

exclude_none=True conflates two distinct user intents: "do not update this field" and "clear this field to null."

Impact

Affects every nullable field on every resource using this pattern: target_date, start_date, parent, point,
description_html, assignees (back to empty), etc. Currently the only workaround is clearing in the Plane web UI.

Proposed fix (two viable shapes)

A. Switch to exclude_unset=True + explicit None for clears

  • Caller passes None to mean "clear," and omits the field entirely to mean "don't change."
  • Requires the data model to distinguish unset from None (Pydantic v2 supports this natively).
  • Breaking change for callers that currently pass None expecting "don't change."

B. Add explicit clear: list[str] parameter to update() methods

  • Caller passes e.g. clear=["target_date", "parent"] and the wrapper injects null for those fields after
    model_dump.
  • Non-breaking; opt-in.
  • More verbose but unambiguous.

Happy to send a PR with whichever shape the maintainers prefer.

Environment

  • plane-sdk 0.2.10 (also present on main HEAD as of 2026-05-17)
  • Plane Cloud workspace
  • Discovered via plane-mcp-server's update_work_item tool, but the bug is in the SDK, not the MCP wrapper.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in plane/api/work_items/base.py around line 102, then search the other resource classes for the same model_dump(exclude_none=True) pattern. Compare how unset fields and explicit None are represented in the update models before choosing between the two proposed approaches. Done means nullable fields can be cleared without turning omitted fields into updates across the affected resources.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.