- Docs
- Flow Producer
- Child Failures
One child dies. Now what?
The default is to keep waiting, which is rarely what you want. These four options let a failed child fail the parent, be ignored, cancel its siblings, or let the parent run on whatever succeeded.
When a Child Fails
Section titled “When a Child Fails”By default a parent just keeps waiting for its remaining children. Four child options change what happens when a child fails terminally (no retries left):
| Option | Behavior |
|---|---|
failParentOnFailure | Parent immediately moves to failed, even if other children are still running |
removeDependencyOnFailure | The failed child is silently dropped from the parent’s dependencies; the parent proceeds as if it never existed |
ignoreDependencyOnFailure | Like the above, but the failure is recorded; the parent can read it via job.getIgnoredChildrenFailures() |
continueParentOnFailure | Parent is promoted to run immediately; it can inspect failures via job.getFailedChildrenValues() and cancel leftover children |
Choose at most one policy per child. The selected policy and any unresolved
failure record are durable: a broker restart cannot reset the child to default
behavior or put an already-released parent back into waiting-children.
A worked example with continueParentOnFailure, useful when the parent should decide how to handle partial failure:
await flow.add({ name: 'pipeline', queueName: 'main', data: {}, children: [ { name: 'step-a', queueName: 'workers', data: {}, opts: { continueParentOnFailure: true } }, { name: 'step-b', queueName: 'workers', data: {}, opts: { continueParentOnFailure: true } }, { name: 'step-c', queueName: 'workers', data: {} }, ],});
const worker = new Worker('main', async (job) => { const failed = await job.getFailedChildrenValues(); // { 'workers:job-abc': 'Error: step-a failed', ... }
if (Object.keys(failed).length > 0) { await job.removeUnprocessedChildren(); // cancel children still waiting return { status: 'partial', failedSteps: failed }; } return { status: 'complete' };}, { embedded: true });import { FlowProducer, Queue, Worker } from 'bunqueue-client';
const flow = new FlowProducer();const queue = new Queue('main');
await flow.add({ name: 'pipeline', queueName: 'main', data: {}, children: [ { name: 'step-a', queueName: 'workers', data: {}, opts: { continueParentOnFailure: true } }, { name: 'step-b', queueName: 'workers', data: {}, opts: { continueParentOnFailure: true } }, { name: 'step-c', queueName: 'workers', data: {} }, ],});
const worker = new Worker('main', async (job) => { const failed = await queue.getFailedChildrenValues(job.id); // { 'workers:job-abc': 'Error: step-a failed', ... }
if (Object.keys(failed).length > 0) { await queue.removeUnprocessedChildren(job.id); // cancel children still waiting return { status: 'partial', failedSteps: failed }; } return { status: 'complete' };});from bunqueue import FlowProducer, Queue, Worker
flow = FlowProducer()queue = Queue("main")
flow.add({ "name": "pipeline", "queueName": "main", "data": {}, "children": [ {"name": "step-a", "queueName": "workers", "data": {}, "opts": {"continue_parent_on_failure": True}}, {"name": "step-b", "queueName": "workers", "data": {}, "opts": {"continue_parent_on_failure": True}}, {"name": "step-c", "queueName": "workers", "data": {}}, ],})
def process(job): failed = queue.get_failed_children_values(job.id) # {"workers:job-abc": "Error: step-a failed", ...}
if failed: queue.remove_unprocessed_children(job.id) # cancel children still waiting return {"status": "partial", "failed_steps": failed} return {"status": "complete"}
Worker("main", process).run()The child-failure queries (getFailedChildrenValues, getIgnoredChildrenFailures, removeUnprocessedChildren) are available in the Bun package and the TypeScript and Python SDKs. The failure options themselves work from PHP like anywhere else; read child outcomes by looking the child IDs up with getJob($childId) / getResult($childId) on the queue.
The child-failure queries (getFailedChildrenValues, getIgnoredChildrenFailures, removeUnprocessedChildren) are available in the Bun package and the TypeScript and Python SDKs. The failure options themselves work from Go like anywhere else; read child outcomes by looking the child IDs up with GetJob(childID) / GetResult(childID) on the queue.
The child-failure queries (getFailedChildrenValues, getIgnoredChildrenFailures, removeUnprocessedChildren) are available in the Bun package and the TypeScript and Python SDKs. The failure options themselves work from Rust like anywhere else; read child outcomes by looking the child IDs up with get_job(child_id) / get_result(child_id) on the queue.
The child-failure queries (getFailedChildrenValues, getIgnoredChildrenFailures, removeUnprocessedChildren) are available in the Bun package and the TypeScript and Python SDKs. The failure options themselves work from Elixir like anywhere else; read child outcomes by looking the child IDs up with get_job(child_id) / get_result(child_id) on the queue.
And with ignoreDependencyOnFailure, when the parent should continue with partial data:
const worker = new Worker('reports', async (job) => { const ignored = await job.getIgnoredChildrenFailures(); // { 'workers:job-abc': 'Error: enrichment API timeout' } return { partial: Object.keys(ignored).length > 0 };}, { embedded: true });const queue = new Queue('reports');
const worker = new Worker('reports', async (job) => { const ignored = await queue.getIgnoredChildrenFailures(job.id); // { 'workers:job-abc': 'Error: enrichment API timeout' } return { partial: Object.keys(ignored).length > 0 };});queue = Queue("reports")
def process(job): ignored = queue.get_ignored_children_failures(job.id) # {"workers:job-abc": "Error: enrichment API timeout"} return {"partial": bool(ignored)}
Worker("reports", process).run()The child-failure queries (getFailedChildrenValues, getIgnoredChildrenFailures, removeUnprocessedChildren) are available in the Bun package and the TypeScript and Python SDKs. The failure options themselves work from PHP like anywhere else; read child outcomes by looking the child IDs up with getJob($childId) / getResult($childId) on the queue.
The child-failure queries (getFailedChildrenValues, getIgnoredChildrenFailures, removeUnprocessedChildren) are available in the Bun package and the TypeScript and Python SDKs. The failure options themselves work from Go like anywhere else; read child outcomes by looking the child IDs up with GetJob(childID) / GetResult(childID) on the queue.
The child-failure queries (getFailedChildrenValues, getIgnoredChildrenFailures, removeUnprocessedChildren) are available in the Bun package and the TypeScript and Python SDKs. The failure options themselves work from Rust like anywhere else; read child outcomes by looking the child IDs up with get_job(child_id) / get_result(child_id) on the queue.
The child-failure queries (getFailedChildrenValues, getIgnoredChildrenFailures, removeUnprocessedChildren) are available in the Bun package and the TypeScript and Python SDKs. The failure options themselves work from Elixir like anywhere else; read child outcomes by looking the child IDs up with get_job(child_id) / get_result(child_id) on the queue.
All four failure-propagation options are ordinary job options and reach the wire in every SDK. The reading helpers (getFailedChildrenValues, getIgnoredChildrenFailures, removeUnprocessedChildren) are currently available in the Bun package, the TypeScript SDK and the Python SDK (on Queue, taking the job id).
Where to go next
Section titled “Where to go next”| Flow Producer | Your first parent/child graph, and what is guaranteed |
| Flow Patterns | Chains, fan-in, trees, reading child results, options |
| Flow Producer Reference | Every producer method, job helper and step field |