Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

fix: safe-empty restock default so restock notification tokens work for any watch - #4249

#4249
Merged
dgtlmoon merged 2 commits into
dgtlmoon:masterdgtlmoon/changedetection.io:masterfrom
ebarkhordar:fix/3490-restock-token-safe-emptyebarkhordar/changedetection.io:fix/3490-restock-token-safe-emptyCopy head branch name to clipboard
Jul 13, 2026
Merged

fix: safe-empty restock default so restock notification tokens work for any watch#4249
dgtlmoon merged 2 commits into
dgtlmoon:masterdgtlmoon/changedetection.io:masterfrom
ebarkhordar:fix/3490-restock-token-safe-emptyebarkhordar/changedetection.io:fix/3490-restock-token-safe-emptyCopy head branch name to clipboard

Conversation

@ebarkhordar

Copy link
Copy Markdown
Contributor

Root cause

{{ restock.price }} (and the other restock.* tokens) are only added to the
notification context for restock watches, in
processors/restock_diff extra_notification_token_values(). The base token set in
NotificationContextData.__init__ (changedetectionio/notification_service.py) has no
restock key, so for a non-restock watch, or for a system-wide notification body, the
token is undefined. That produces two failures:

  1. Send time: rendering a body containing {{ restock.price }} for a non-restock watch
    raises jinja2 UndefinedError: 'restock' is undefined (the exact error in 'restock' is undefined #3490).
  2. Save time: ValidateJinja2Template builds its valid-token set from the same defaults,
    so a system-wide body using {{ restock.price }} is rejected unless a restock watch
    happens to exist.

Invariant

A notification token that is valid in a per-watch body should also be a valid,
non-crashing token in a system-wide body, independent of the current watch inventory.

Fix

Add a safe-empty 'restock': {} to the NotificationContextData default token set.
Restock watches still override it with the real price object via
extra_notification_token_values(), so their notifications are unchanged. Every other
watch now renders {{ restock.price }} as empty rather than raising, and system-wide
bodies validate.

This is intentionally the narrow token-availability fix for #3490, not the separate
restock-data storage change noted in the issue thread.

How I verified

In a clean python:3.11-slim Docker container against master HEAD (ee84ece):

  • Reproduced both failures on master: render('{{ restock.price }}', **NotificationContextData())
    raises UndefinedError, and ValidateJinja2Template raises ValidationError, both
    'restock' is undefined.
  • Added tests/test_notification_restock_token.py covering the default token, the
    send-time render, and the save-time validation. It fails on master (3 failed) and
    passes with the fix (3 passed).
  • Ran the existing tests/llm/test_notification_tokens.py and
    tests/llm/test_llm_restock_plugin.py with the fix: 36 passed.

I did not run the full browser/selenium/playwright suite or the SMTP integration tests;
this change only touches the in-memory default token dict.

Run: pytest tests/test_notification_restock_token.py

AI assistance was used to help write this change; I reproduced and verified it as
described above.

Fixes #3490

The {{ restock.price }} family of notification tokens is only injected for
restock watches (processors/restock_diff extra_notification_token_values()).
For a non-restock or system-wide notification body the `restock` token was
absent from NotificationContextData's default set, so it raised UndefinedError
at send time and failed save-time template validation.

Add a safe-empty 'restock': {} default. Restock watches still override it with
real price data; every other watch now renders the token as empty instead of
crashing, and system-wide bodies validate. Fixes dgtlmoon#3490.
@dgtlmoon

Copy link
Copy Markdown
Owner

yeah this should be solved as part of a bigger refactor, but this is a good enough fix for now , thanks

Comment thread changedetectionio/notification_service.py Outdated
@dgtlmoon
dgtlmoon merged commit aa60984 into dgtlmoon:master Jul 13, 2026
34 checks passed
@ebarkhordar
ebarkhordar deleted the fix/3490-restock-token-safe-empty branch July 13, 2026 07:45
@ebarkhordar

Copy link
Copy Markdown
Contributor Author

Thanks for merging. Agreed, the storage refactor is the right long term home for this, glad the small fix covers the gap until then.

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.

'restock' is undefined

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.