Thang Kieu
11/26/2025, 5:53 AMMarvin
11/26/2025, 5:53 AMMarvin
11/26/2025, 6:04 AMprefect deployment run <FLOW_NAME>/<DEPLOYMENT_NAME> --watch
- Or script it: query crashed runs with the Python client and programmatically create new runs of the corresponding deployments. I can share a snippet if helpful.
Notes:
- There isn’t a built-in “retry task run” automation action. Automations can trigger actions like “run-deployment” (creating a new flow run), send notifications, pause/resume things, etc., but they don’t retroactively “retry” a completed task run.
- Automations and event behavior: Automations and Event Triggers
If you tell me whether you want to re-run entire flow runs or target specific tasks, I can propose the most straightforward approach (and provide code/CLI examples).Thang Kieu
11/26/2025, 6:11 AMThang Kieu
11/26/2025, 6:13 AMMarvin
11/26/2025, 6:13 AMMarvin
11/26/2025, 6:15 AM{{ event.payload }}, {{ event.event }}, {{ event.resource['prefect.resource.id'] }})
- flow_run: if the event was a flow-run event (e.g., {{ flow_run.id }}, {{ flow_run.name }}, {{ flow_run.parameters['foo'] }})
- task_run: if the event was a task-run event (similar fields to flow_run)
- deployment, flow, labels, automation, firing, etc.
How to use it in the Run a deployment action:
- For each parameter you want to populate dynamically, wrap it as a Jinja template object:
parameters:
user_id:
__prefect_kind: jinja
template: "{{ flow_run.parameters.get('user_id', 'unknown') }}"
previous_run_id:
__prefect_kind: jinja
template: "{{ flow_run.id }}"
- If you want to pass the entire event payload as a dict to the downstream flow, use a JSON wrapper:
parameters:
payload:
__prefect_kind: json
value:
__prefect_kind: jinja
template: "{{ event.payload | tojson }}"
Common examples:
- Re-run a downstream deployment with the same parameters as the failed flow run:
actions:
- type: run-deployment
source: selected
deployment_id: <TARGET_DEPLOYMENT_ID>
parameters:
original_run_id:
__prefect_kind: jinja
template: "{{ flow_run.id }}"
same_params:
__prefect_kind: json
value:
__prefect_kind: jinja
template: "{{ flow_run.parameters | tojson }}"
- Use task-run information:
parameters:
task_name:
__prefect_kind: jinja
template: "{{ task_run.name }}"
error_msg:
__prefect_kind: jinja
template: "{{ task_run.state.message }}"
Docs and references:
- Automations templating with Jinja: Concepts: Automations
- Access parameters in templates: How-to: Access parameters in templates
- Pass event payloads to flows: How-to: Passing event payloads to flows
- Event triggers concept: Concepts: Event Triggers
If you share what fields you need from the triggering run, I can sketch the exact parameter block you’ll want.Thang Kieu
11/26/2025, 6:30 AMMarvin
11/26/2025, 6:30 AMMarvin
11/26/2025, 6:31 AM{
"__prefect_kind": "jinja",
"template": "{{ flow_run.id }}"
}
- Jinja that produces non-strings (dict/list/number) via JSON casting:
{
"__prefect_kind": "json",
"value": {
"__prefect_kind": "jinja",
"template": "{{ flow_run.parameters | tojson }}"
}
}
Examples
1) Run a deployment action: pass fields from the triggering flow run
parameters: {
"previous_run_id": {
"__prefect_kind": "jinja",
"template": "{{ flow_run.id }}"
},
"same_params": {
"__prefect_kind": "json",
"value": {
"__prefect_kind": "jinja",
"template": "{{ flow_run.parameters | tojson }}"
}
}
}
2) Call a webhook: use event payload + run info
payload: {
"customer_id": {
"__prefect_kind": "jinja",
"template": "{{ event.payload.customer_id }}"
},
"run_id": {
"__prefect_kind": "jinja",
"template": "{{ flow_run.id }}"
},
"raw": {
"__prefect_kind": "json",
"value": {
"__prefect_kind": "jinja",
"template": "{{ event.payload | tojson }}"
}
}
}
Notes
- Without these wrappers, JSON strings won’t be treated as templates.
- Use tojson when your template should render to a structured JSON value (dict/list), not a string.
- Available context: event, flow_run, task_run, deployment, labels, automation, firing, etc.
Docs
- Templating in Automations: Concepts: Automations
- Access parameters in templates: How-to: Access parameters in templates
- Passing event payloads: How-to: Passing event payloads to flows
Tell me which action/field you’re configuring and the values you want to pass, and I’ll write the exact JSON you can paste into the UI.Thang Kieu
11/26/2025, 6:44 AMFailed to render template due to the following error: TypeError('Object of type ChainableUndefined is not JSON serializable')\nTemplate source:\n{{ event.payload | tojson }}Marvin
11/26/2025, 6:44 AMMarvin
11/26/2025, 6:44 AMtojson. ChainableUndefined is Jinja’s “undefined” placeholder, and it can’t be JSON-serialized.
Why it happens:
- Many Prefect system events don’t include a payload. If you reference {{ event.payload }} and it’s missing, you’ll get ChainableUndefined.
- The same applies to nested lookups like event.payload.user_id when payload is missing.
Fix: add a safe default before calling tojson (or before accessing nested fields).
- Entire payload as JSON:
{
"__prefect_kind": "json",
"value": {
"__prefect_kind": "jinja",
"template": "{{ event.payload | default({}) | tojson }}"
}
}
- Single field from payload (string param):
{
"__prefect_kind": "jinja",
"template": "{{ (event.payload | default({})).get('user_id', '') }}"
}
- If you actually want flow parameters (not event payload), use `flow_run.parameters`:
{
"__prefect_kind": "json",
"value": {
"__prefect_kind": "jinja",
"template": "{{ flow_run.parameters | default({}) | tojson }}"
}
}
Notes:
- default({}) replaces undefined with an empty dict, preventing ChainableUndefined.
- For non-string params (dict/list), keep the outer __prefect_kind: "json" wrapper and put your Jinja inside its value.
- If your automation isn’t triggered by a flow-run event, flow_run may be undefined too; use the same default pattern or switch to the correct context object.
Docs:
- Templating in Automations: Concepts: Automations
- Passing event payloads: How-to: Passing event payloads
If you share the event type that’s triggering your automation and the parameter you want to fill, I’ll give you the exact JSON to paste into the UI.Thang Kieu
11/26/2025, 6:59 AM{
"payload": {
"job_id": "f96c518a-fa2c-4adf-85cf-40f346e8f2b3",
"callback_url": "<https://host.docker.internal:20002/latest/knowledge/bases/5a2ea7be2b1342928b053df820cbfbf6/rag>",Marvin
11/26/2025, 7:00 AMMarvin
11/26/2025, 7:01 AMflow_run.parameters['payload']['job_id'] is undefined at render time. In Prefect’s Jinja environment, undefined values don’t error by default — they render as an empty string.
Use defensive lookups with defaults:
{
"job_id": {
"__prefect_kind": "jinja",
"template": "{{ (flow_run.parameters | default({})).get('payload', {}).get('job_id', '') }}"
}
}
If that still comes back empty, quickly debug what the action can actually see by adding a temporary notification action (or a one-off parameter) that prints the context:
{
"__prefect_kind": "jinja",
"template": "event={{ event.event }}; flow_run_defined={{ flow_run is defined }}; params={{ flow_run.parameters | default({}) | tojson }}"
}
Things to verify:
- The automation is triggered by a flow-run event (or an event that has a related flow run). If it’s a task-run-only event and flow_run isn’t attached in context, your template will be undefined.
- The triggering run actually has parameters.payload.job_id at the time the automation fires. Sometimes the run you’re looking at in the UI is the new run created by the action, not the triggering run.
If you share your automation’s trigger (event type and match rules), I can tailor the exact template to your event (e.g., using task_run context if needed). Docs for reference:
- Templating with Jinja: Automations templating
- Access parameters in templates: Access parameters in templatesThang Kieu
11/26/2025, 7:07 AMevent=; flow_run_defined=False; params={}Marvin
11/26/2025, 7:07 AMMarvin
11/26/2025, 7:08 AM{
"__prefect_kind": "jinja",
"template": "event_defined={{ event is defined }}; flow_run_defined={{ flow_run is defined }}; task_run_defined={{ task_run is defined }}"
}
Once a flow_run is actually present, your parameter can be:
{
"job_id": {
"__prefect_kind": "jinja",
"template": "{{ (flow_run.parameters | default({})).get('payload', {}).get('job_id', '') }}"
}
}
If you share your trigger setup (event type, posture, and any “match related” settings), I can suggest the exact changes so the flow_run context is available.Thang Kieu
11/26/2025, 7:12 AM{
"type": "event",
"match": {
"prefect.resource.id": "prefect.flow-run.*"
},
"match_related": {},
"after": [],
"expect": [
"prefect.flow-run.Failed",
"prefect.flow-run.Crashed",
"prefect.flow-run.Cancelled"
],
"for_each": [
"prefect.resource.id"
],
"posture": "Reactive",
"threshold": 1,
"within": 0
}Marvin
11/26/2025, 7:12 AMThang Kieu
11/26/2025, 7:12 AMMarvin
11/26/2025, 7:14 AMevent and flow_run in the template context.
Given your debug output was:
event=; flow_run_defined=False; params={}
that almost always means the template was rendered via the UI “Test” button (which does not supply real event/run context), or by a non-event (proactive) evaluation. In those cases, event and flow_run are undefined and render as empty strings.
What to do:
1) Trigger a real event to test
- Cause a real flow run to Fail/Crash/Cancel and let the automation fire.
- Add a temporary Send notification action with a body like:
{{ "event_defined=" ~ (event is defined) ~ "; flow_run_defined=" ~ (flow_run is defined) ~ "; task_run_defined=" ~ (task_run is defined) }}
You should see both event_defined=True and flow_run_defined=True on a real firing.
2) Use a defensive template for your parameter
- Once you confirm flow_run is present, this will safely read the nested value:
{
"job_id": {
"__prefect_kind": "jinja",
"template": "{{ (flow_run.parameters | default({})).get('payload', {}).get('job_id', '') }}"
}
}
3) If you ever switch to a Task Run event
- flow_run may be undefined. Either target a flow-run event (as you do now) or reference task_run (and/or ensure the related flow run is loaded via your trigger’s match rules).
References:
- Automations templating: Templating with Jinja
- How-to: Access parameters in templates: Access parameters in templates
If you confirm this fired on a real failed/crashed/cancelled flow run and it still shows flow_run_defined=False, share the flow run ID + the automation name/time window and I’ll help dig in further.Thang Kieu
11/26/2025, 7:16 AMMarvin
11/26/2025, 7:16 AMMarvin
11/26/2025, 7:17 AMevent=; flow_run_defined=False; params={}
means the action ran without a triggering event/flow_run in its template context.
Most common causes:
- The action didn’t fire on a real flow-run event (e.g., it ran outside a Failed/Crashed/Cancelled event window).
- A different automation/action executed (e.g., a proactive evaluation or a manual run of the action).
- You’re inspecting the downstream run’s action output instead of the firing created by the failing run.
What to check
- In the UI, open Automations > your automation > Firings > click the firing that produced the message.
- Confirm “Triggering event” is present and is one of prefect.flow-run.Failed/Crashed/Cancelled.
- If “Triggering event” is missing, the context will not include event/flow_run; we should dig into why that firing occurred.
Once you’re on a real flow-run firing, this template will safely grab your job_id:
{
"job_id": {
"__prefect_kind": "jinja",
"template": "{{ (flow_run.parameters | default({})).get('payload', {}).get('job_id', '') }}"
}
}
Practical fallback (works even if you can’t read parameters in the automation)
1) Pass the original run id to the downstream run:
{
"original_run_id": {
"__prefect_kind": "jinja",
"template": "{{ event.resource['prefect.resource.id'].split('.')[-1] }}"
}
}
2) In the downstream flow, fetch the parameters from the original run:
from prefect import flow
from prefect.client.orchestration import get_client
@flow
async def downstream(original_run_id: str):
async with get_client() as client:
fr = await client.read_flow_run(original_run_id)
params = fr.parameters or {}
job_id = params.get("payload", {}).get("job_id")
# use job_id...
If you can share:
- The automation name
- A specific “Firing” link/time where you saw the empty context
- The original flow run ID that should have triggered it
…I’ll pinpoint why the context was empty and give you the exact JSON to paste.
Refs:
- Templating with Jinja: Automations templating
- Access parameters in templates: Access parameters in templates
- Passing event payloads to flows: Passing event payloads