Madushan Pathirana
09/06/2025, 3:23 AMMarvin
09/06/2025, 3:23 AMMarvin
09/06/2025, 3:28 AM{{ state.name }}
, Prefect tried to resolve a placeholder that the block doesn’t know — hence the KeyError.
How to fix
1) Put all event/state details into the action’s Jinja (subject/body), not inside the webhook block.
2) In the webhook block, reference only {{ subject }}
and/or {{ body }}
(and any {{ secrets.* }}
you define).
Working example
- Automation action templates (subject/body) using the event context:
Subject:
[{{ event.payload.state.name | default("unknown") }}] Flow run {{ event.resource.name | default("unnamed") }}
Body:
Flow run {{ event.resource.id }} changed to {{ event.payload.state.name | default("unknown") }}.
Event: {{ event.name }}
Timestamp: {{ event.occurred | default("") }}
Resource:
- Kind: {{ event.resource.kind | default("") }}
- Name: {{ event.resource.name | default("") }}
- ID: {{ event.resource.id | default("") }}
{{ "See in UI: " ~ (event.resource | ui_url) if event is defined }}
- CustomWebhookNotificationBlock configuration referencing only subject/body (and optional secrets):
url: <https://example.com/webhook>
method: POST
headers:
Content-Type: application/json
Authorization: Bearer {{ secrets.token }}
json_data:
title: "{{ subject }}"
message: "{{ body }}"
Notes and tips
- Do not use {{ state.name }}
(or {{ event.payload.state.name }}
) inside the webhook block fields. Put those into the action’s subject/body, then reference `{{ subject }}`/`{{ body }}` in the block.
- The Automations Jinja context typically includes variables like event
, resource
, and related
. Useful Jinja filters include ui_url
and ui_resource_events_url
for building UI links.
- If you need structured fields (e.g., status, flow name) in the webhook payload, compute them inside the body template and keep your webhook payload mapping simple (e.g., send subject
and body
).
Docs for deeper reference
- Automations templating, variables, and filters: Access event data in templates
- Jinja filters (e.g., ui_url): Events Jinja filters
- Notification blocks (Custom Webhook): Notification blocks API
If you share:
- Your current CustomWebhookNotificationBlock configuration (url/headers/json_data)
- The exact subject/body you’re using in the Automation
I can suggest precise changes to remove the KeyError and get notifications flowing.Madushan Pathirana
09/06/2025, 7:09 AMMarvin
09/06/2025, 7:09 AMMarvin
09/06/2025, 7:10 AMsubject
and body
.
- The notification block (SlackWebhook or Custom Webhook) only receives those two strings and can only use placeholders like {{ subject }}
, {{ body }}
, {{ name }}
(and {{ secrets.* }}
if configured). It does NOT have access to event
, state
, flow_run
, etc. in its own URL/headers/json_data fields.
- If you put {{ state.name }}
(or similar) into the block fields, you’ll get the KeyError you saw.
Known‑working setup for Slack via Automation
1) Block
- Use a SlackWebhook block (the same one you used in your flow), no templating needed in the block. Just the webhook URL.
2) Automation
- Trigger: e.g., Flow run state entered Failed (or your choice)
- Action: Send notification
- Block: your SlackWebhook block (e.g., credilinq-ds-slack)
- Subject:
[{{ event.payload.state.name | default("unknown") }}] {{ event.resource.name | default("flow run") }}
- Body:
Flow run {{ event.resource.id }} changed to {{ event.payload.state.name | default("unknown") }}.
Event: {{ event.name }}
{{ (event.resource | ui_url) if event is defined }}
Minimal test to isolate templating issues
- Subject:
Automation test
- Body:
Hello from Prefect Automations
If this delivers to Slack, your block and action path are good — then add event fields gradually. If it still fails, the problem is not templating; share the latest “Action failed” message and we’ll dig in.
If you were using a Custom Webhook block for Slack
- Don’t put {{ state.* }}
in the block’s json_data. Instead, forward the rendered subject/body into the JSON Slack expects:
url: <https://hooks.slack.com/services/XXX/YYY/ZZZ>
method: POST
headers:
Content-Type: application/json
json_data:
text: "{{ subject }}\n{{ body }}"
Helpful references
- Notification blocks API: Notification blocks
- Automations templating context and examples: Automation templates
- Jinja filters for URLs: Events Jinja filters
If you can share:
- The Automation’s Action config (which block you selected and the exact subject/body)
- The latest ActionFailed error from the Server logs or the Automation run
I’ll pinpoint the fix.Madushan Pathirana
09/06/2025, 7:11 AMMarvin
09/06/2025, 7:11 AMMarvin
09/06/2025, 7:13 AMSubject:
Automation test
Body:
Hello from Prefect Automations
- If this delivers to Slack, the block and outbound network are fine and the issue is with your Jinja templates. Add fields back gradually.
3) If you are using a Custom Webhook (not the SlackWebhook block), make sure you do NOT put event placeholders in the block fields. Only use the action’s subject/body inside the block:
json_data:
text: "{{ subject }}\n{{ body }}"
- Do not use placeholders like {{ state.name }}
in the block itself — that’s what caused your earlier KeyError. Put event data only in the Automation’s subject/body.
Known‑good Jinja for Automations subject/body (SlackWebhook block)
Subject:
[{{ event.payload.state.name | default("unknown") }}] {{ event.resource.name | default("flow run") }}
Body:
Flow run {{ event.resource.id }} changed to {{ event.payload.state.name | default("unknown") }}.
Event: {{ event.name }}
{{ (event.resource | ui_url) if event is defined }}
Where to look for more detail
- Automations Activity in the UI will show failed action runs and usually includes the failure message.
- Server logs around that timestamp often include the original exception just before “Notification failed”. If possible, re-run with DEBUG logging to capture the full error.
- For a quick test, restart your server with debug logging enabled (e.g., set logging to DEBUG for server; if you need exact steps for your setup, I can provide them).
CLI to inspect your automation
prefect automations ls
prefect automations inspect <AUTOMATION_ID>
Common pitfalls
- Using event/state placeholders inside the Custom Webhook block (json_data/headers/url) instead of only using them in subject/body.
- Typos in Jinja keys; prefer defensive defaults:
- {{ event.payload.state.name | default("unknown") }}
- {{ event.resource.name | default("flow run") }}
- Network egress differences: the flow run’s worker can reach Slack, but the server process also needs outbound internet. Since both are on the same EC2, this is unlikely but worth confirming if the simple template still fails.
If the simple “Automation test” subject/body still fails, please share:
- A screenshot or the exact action config (which block selected, subject/body)
- The full log lines around “Action failed: 'Notification failed'”
- Whether the action is using SlackWebhook or Custom Webhook
I’ll pinpoint the fix from there.
References
- Notification blocks: Notification blocks API
- Automations templating context: Automation templates
- Jinja filters (e.g., ui_url): Events Jinja filtersMadushan Pathirana
09/06/2025, 7:15 AMMarvin
09/06/2025, 7:15 AMMarvin
09/06/2025, 7:18 AMpython - << 'PY'
from prefect.blocks.notifications import SlackWebhook
b = SlackWebhook.load("credilinq-ds-slack")
b.notify(subject="Automation test", body="From server env")
print("Sent from server env")
PY
- If this fails here, it will fail in Automations; fix the env var and try again.
3) Re-test your Automation with the simple subject/body:
Subject:
Automation test
Body:
Hello from Prefect Automations
If it still fails after setting the key:
- Double-check the Automation is using the SlackWebhook block (not a Custom Webhook).
- Inspect the block and confirm it exists and is the one you expect:
prefect block ls
prefect block inspect <BLOCK_TYPE_SLUG>/<BLOCK_NAME>
Useful docs
- Storing secrets and encryption key: Store secrets and encryption key
- Notification blocks API: Notification blocks API
If you can share:
- How you start the Prefect Server (so we can confirm where to set env vars)
- Output of the quick Python test from the server’s environment
- Which block the Automation action is pointing to
I’ll help you get it across the finish line.