acocodes
10/13/2025, 8:37 AMTypeError(\"unsupported operand type(s) for +=: 'frozenset' and 'tuple'\")"Marvin
10/13/2025, 8:37 AMMarvin
10/13/2025, 8:40 AMapprise.NOTIFY_TYPES changed from a tuple to a frozenset.
- Older Prefect code tried to do += on that value when initializing notification blocks, which raises:
TypeError: unsupported operand type(s) for +=: 'frozenset' and 'tuple'
- This was fixed in Prefect by adding a version-aware check for frozenset vs tuple.
References:
- Issue: TypeError with apprise 1.9.4
- PR: Fix TypeError with apprise 1.9.4 when adding notify type
- (For 2.x backport context) PR: Fix anyio/apprise compatibility issues
How to fix it:
- Best: Upgrade Prefect to a version that includes the fix (latest 3.x).
pip install -U prefect
- If you can’t upgrade Prefect immediately, pin Apprise back to 1.9.3 (before the change to frozenset):
pip install "apprise==1.9.3"
Note: This may impact your MS Teams compatibility if you were relying on changes in 1.9.4+.
Could you share:
- Your Prefect version (python -c "import prefect, apprise; print(prefect.__version__, apprise.__version__)")
- A short traceback snippet showing where this is thrown (likely during notification block init in your automation)
With that, I can confirm whether you’re on a Prefect version that already contains the fix or if an upgrade/pin is the quickest path.acocodes
10/13/2025, 8:43 AMMarvin
10/13/2025, 8:43 AMMarvin
10/13/2025, 8:44 AMsrc/prefect/blocks/notifications.py to handle apprise.NOTIFY_TYPES being a frozenset (Apprise ≥ 1.9.4) or a tuple (older Apprise).
Direct links:
- PR diff: Fix TypeError with apprise 1.9.4 when adding notify type
- Permalink to the code lines referenced in the original report: notifications.py L36–L42
The logic added looks like this (simplified):
import apprise
from prefect.blocks.notifications import PREFECT_NOTIFY_TYPE_DEFAULT
# Handle Apprise >= 1.9.4 (frozenset) vs older Apprise (tuple)
if isinstance(apprise.NOTIFY_TYPES, frozenset):
apprise.NOTIFY_TYPES = apprise.NOTIFY_TYPES | {PREFECT_NOTIFY_TYPE_DEFAULT}
else:
apprise.NOTIFY_TYPES += (PREFECT_NOTIFY_TYPE_DEFAULT,)
For users on the 2.x EOL branch, the same compatibility fix was backported in PR #18741.acocodes
10/13/2025, 9:26 AMMarvin
10/13/2025, 9:26 AMMarvin
10/13/2025, 9:31 AM{{ payload.state.message }}
- Task-run events: {{ payload.state.message }}
Example templates:
Flow failed: {{ payload.flow_run.name }}
Status: {{ payload.state.type }}
Error: {{ payload.state.message }}
Run ID: {{ payload.flow_run.id }}
Link: {{ payload.flow_run.url }}
Task failed: {{ payload.task_run.name }} in {{ payload.flow_run.name }}
Status: {{ payload.state.type }}
Error: {{ payload.state.message }}
Run: {{ payload.flow_run.name }} ({{ payload.flow_run.id }})
Notes and tips:
- Full tracebacks are not included in the event payload. For deep details, link to the run page ({{ payload.flow_run.url }}) or use a custom webhook/flow to fetch logs or state details from the API.
- Available keys differ by event type (flow-run vs task-run), but common fields include:
- payload.flow_run.name, payload.flow_run.id, payload.flow_run.url
- payload.task_run.name, payload.task_run.id
- payload.state.type, payload.state.name, payload.state.message
- To see exactly what’s available for your event, add a temporary Call Webhook action to a service like webhook.site and inspect the JSON payload your automation sends.
Docs for reference:
- Creating automations
- Access parameters in templates
- Notification blocks API
If you tell me whether you’re templating Slack, Teams, or email, I can tailor a ready-to-paste example.