Skip to content

fix: accept a pause_notifications effect without a scope - #102

Merged
lmjabreu merged 1 commit into
mainfrom
lmjabreu/inspiring-leavitt-a5efd7
Oct 14, 2026
Merged

lmjabreu merged 1 commit into
mainfrom
lmjabreu/inspiring-leavitt-a5efd7

Conversation

@lmjabreu

Copy link
Copy Markdown
Contributor

Overview

UserStatusSchema (added in #100) required effects.pauseNotifications.scope.mode. A Status can be written by other Todoist clients through user_update, and comms-ios decodes PauseNotifications as an empty struct, so a stored pause_notifications: {} is plausible. The backend omits unset fields on this route, so scope can come back absent and getSessionUser / getUser throw a ZodError for every caller. scope and scope.mode are now optional. SetStatusArgs is unchanged.

Reference

Found in the review of Doist/comms-cli#77, which reproduced the crash with a fake server returning effects: {pause_notifications: {}}.

Backend, read from main of Doist/comms-backend with gh api (not run):

  • get_session_user is declared with response_model_exclude_unset=True (twist/domains/users/api.py).
  • PauseNotificationsEffect.scope is filled by default_factory (twist/models/dto/users.py), so a scope that was never set is not serialised.

Not verified: where the stored status is turned into UserStatus on the read path. I looked in twist/models/user_views.py and user_profile.py and did not find it, so I don't know whether the DTO is built by validation or by construction. If it is built by validation, the default would count as set and scope would come back as {"mode": "all"}. Nothing was run against a real backend, so whether {} actually reaches the SDK without scope is still unconfirmed. The change is safe either way, since it only loosens parsing.

Changelog

Fix a crash when reading a user whose status pauses notifications without a scope.

Test plan

  1. On main, run npx vitest run src/clients/users-client.test.ts. The new test "parses a pause_notifications effect stored without a scope" fails with a ZodError.
  • On this branch the same command passes, along with npm test, npm run type-check and npm run check.

🤖 Generated with Claude Code

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@lmjabreu

Copy link
Copy Markdown
Contributor Author

@doistbot /review

@doistbot doistbot left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR updates fix: accept a pause_notifications effect without a scope. No issues were flagged in the reviewed diff.

Share Feedback • Review Logs

@lmjabreu
lmjabreu marked this pull request as ready for review October 14, 2026 00:41
@lmjabreu
lmjabreu merged commit d2ef405 into main Oct 14, 2026
5 checks passed
@lmjabreu
lmjabreu deleted the lmjabreu/inspiring-leavitt-a5efd7 branch October 14, 2026 22:09
doist-release-bot Bot added a commit that referenced this pull request Oct 14, 2026
## [3.4.1](v3.4.0...v3.4.1) (2026-10-14)

### Bug Fixes

* accept a pause_notifications effect without a scope ([#102](#102)) ([d2ef405](d2ef405))
@doist-release-bot

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.4.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants