<@ULVA73B9P> prefect.server.events.actions - Acti...
# ask-marvin
m
@Marvin prefect.server.events.actions - Action failed: 'The notification block was invalid: KeyError("json_data/Placeholder(full_match=\'{{ state.name }}\', name=\'state.name\', type=<PlaceholderType.STANDARD: \'standard\'>)")' added custom webhook, got this warning and i am not getting notifications
m
thought for 332.1 seconds
Thanks for the error snippet — that points to the root cause. What’s happening - In Prefect 3.x Automations, the SendNotification action renders your subject/body with a rich Jinja context (e.g., event data). - However, the CustomWebhookNotificationBlock itself only knows about a very small set of placeholders when it renders its fields (url, headers, json_data, etc.). - Specifically, the webhook block can substitute: subject, body, name (block name), and secrets. It does not have access to event/state/flow_run/task_run. - Because your block’s json_data used
{{ 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:
Copy code
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):
Copy code
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.
m
@Marvin this code works @flow(name="EBAY",flow_run_name='{seller_id}', log_prints=True,task_runner=ThreadPoolTaskRunner(max_workers=8)) def run(seller_id:str): slack = SlackWebhook.load("credilinq-ds-slack") try: slack.notify(subject = f"Flow runing {seller_id}" ,body=f"Flow started") print("Sent!") except Exception as e: print("Failed:", e) but automation block to send notifications slack doesnt work
m
thought for 65.9 seconds
Got it — thanks for the code snippet. Since sending via the SlackWebhook block inside your flow works, your webhook URL and block are fine. The failure in Automations is almost certainly due to templating: the Automation action can render rich event data into the subject/body, but the notification block itself cannot resolve event/state placeholders inside its own fields. Key points - The Send notification action renders Jinja using the event context into
subject
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:
Copy code
[{{ event.payload.state.name | default("unknown") }}] {{ event.resource.name | default("flow run") }}
- Body:
Copy code
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:
Copy code
Automation test
- Body:
Copy code
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:
Copy code
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.
m
@Marvin found this in prefect server logs prefect.server.events.actions - Action failed: 'Notification failed'
m
thought for 87.7 seconds
Thanks — that “Notification failed” is the generic wrapper the action emits when the underlying notification call raises an error. Since your SlackWebhook block works from inside your flow, this usually comes down to how the Automation is templated or which block it’s targeting. Quickest path to isolate the issue 1) Ensure the Automation action is using the SlackWebhook block (not a Custom Webhook). - In the action, pick your existing block: credilinq-ds-slack. 2) Temporarily remove all Jinja from the Automation subject/body and try again:
Copy code
Subject:
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:
Copy code
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)
Copy code
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
Copy code
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 filters
m
@Marvin Subject: Automation test Body: Hello from Prefect Automations this faild too
m
thought for 142.5 seconds
Thanks — if even a plain “Automation test” subject/body fails, the problem is not your Jinja. The most common cause in this situation is that the Prefect Server process cannot read/decrypt the SlackWebhook block’s secret URL. Why this happens - SlackWebhook stores its URL as an encrypted secret. - Prefect uses the PREFECT_BLOCKS_ENCRYPTION_KEY to encrypt/decrypt secret fields. - Your flow run works because the worker process can decrypt the block (it likely has the key set). - The Automation action runs inside the Prefect Server process; if that process does not have the same PREFECT_BLOCKS_ENCRYPTION_KEY, the block decrypt fails and you get “Notification failed”. What to do 1) Ensure the server process has the same encryption key as your workers/CLI: - Set PREFECT_BLOCKS_ENCRYPTION_KEY in the environment that launches Prefect Server. - If you use systemd/Docker, add it to that service/container env. - Restart the Prefect Server after setting it. 2) Quick verification from the server environment - In the same shell/env you use to start Prefect Server, run:
Copy code
python - << '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:
Copy code
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:
Copy code
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.