Documentation Index Fetch the complete documentation index at: https://mintlify.com/taskforcesh/bullmq/llms.txt
Use this file to discover all available pages before exploring further.
In certain workflows, you may need a parent job to fail immediately if any of its child jobs fail. The failParentOnFailure option allows you to achieve this behavior. When set to true on a child job, it ensures that if the child fails, its parent job is also marked as failed.
Key Behavior
Selective Only children with failParentOnFailure: true will trigger parent failure
Recursive Failure propagates up the hierarchy to grandparents and beyond
Immediate Parent fails as soon as qualifying child fails
Lazy Marking Parent is marked failed lazily when next processed
Basic Usage
import { FlowProducer } from 'bullmq' ;
const flow = new FlowProducer ({ connection });
const originalTree = await flow . add ({
name: 'root-job' ,
queueName: 'topQueueName' ,
data: {},
children: [
{
name: 'child-job' ,
data: { idx: 0 , foo: 'bar' },
queueName: 'childrenQueueName' ,
// This child will fail its parent if it fails
opts: { failParentOnFailure: true },
},
{
name: 'another-child' ,
data: { idx: 1 , foo: 'foo' },
queueName: 'childrenQueueName' ,
// No failParentOnFailure; its failure won't affect the parent
},
],
});
Recursive Failure Propagation
The failure can cascade through multiple levels of the hierarchy:
const flow = new FlowProducer ({ connection });
const originalTree = await flow . add ({
name: 'root-job' ,
queueName: 'topQueueName' ,
data: {},
children: [
{
name: 'child-job' ,
data: { idx: 0 , foo: 'bar' },
queueName: 'childrenQueueName' ,
// This child will fail its parent if it fails
opts: { failParentOnFailure: true },
children: [
{
name: 'grandchild-job-1' ,
data: { idx: 1 , foo: 'bah' },
queueName: 'grandChildrenQueueName' ,
// This grandchild will fail its parent if it fails
opts: { failParentOnFailure: true },
},
{
name: 'grandchild-job-2' ,
data: { idx: 2 , foo: 'baz' },
queueName: 'grandChildrenQueueName' ,
// No failParentOnFailure; its failure won't affect the parent
},
],
},
{
name: 'child-job-2' ,
data: { idx: 3 , foo: 'foo' },
queueName: 'childrenQueueName' ,
// No failParentOnFailure; its failure won't affect the parent
},
],
});
As soon as a child with this option fails, the parent job will be marked as failed lazily. A worker must process the parent job before it transitions to the failed state. The failure will result in an UnrecoverableError with the message “child failed” .
How It Works
Understanding the failure propagation flow:
grandchild-job-1 fails → Its parent (child-job) fails because failParentOnFailure: true
child-job fails → Since it also has failParentOnFailure: true, the root-job fails
grandchild-job-2 fails → child-job does NOT fail (no failParentOnFailure on grandchild-job-2)
child-job-2 fails → root-job remains unaffected (no failParentOnFailure on child-job-2)
Child with failParentOnFailure fails
A child job with failParentOnFailure: true encounters an error and moves to failed state.
Parent is marked for failure
BullMQ marks the parent job to fail, but the transition happens lazily.
Worker processes parent
When a worker attempts to process the parent, it immediately fails with an UnrecoverableError.
Recursive validation
If the parent also has failParentOnFailure: true, the process repeats up the hierarchy.
Use Cases
Critical Path Dependencies
When certain child jobs are critical to the workflow and their failure should abort the entire process: const flow = await flowProducer . add ({
name: 'deploy-application' ,
queueName: 'deployment' ,
data: {},
children: [
{
name: 'build-code' ,
queueName: 'build' ,
data: {},
// Critical: if build fails, deployment must fail
opts: { failParentOnFailure: true },
},
{
name: 'run-tests' ,
queueName: 'testing' ,
data: {},
// Critical: if tests fail, deployment must fail
opts: { failParentOnFailure: true },
},
{
name: 'update-docs' ,
queueName: 'documentation' ,
data: {},
// Not critical: docs can fail without affecting deployment
},
],
});
Ensure payment workflows fail fast when critical validation steps fail: const paymentFlow = await flowProducer . add ({
name: 'process-payment' ,
queueName: 'payments' ,
data: { orderId: '12345' },
children: [
{
name: 'validate-card' ,
queueName: 'validation' ,
data: {},
// Critical: invalid card should fail payment
opts: { failParentOnFailure: true },
},
{
name: 'check-fraud' ,
queueName: 'fraud-detection' ,
data: {},
// Critical: fraud detection failure should fail payment
opts: { failParentOnFailure: true },
},
{
name: 'send-receipt' ,
queueName: 'notifications' ,
data: {},
// Not critical: receipt failure shouldn't fail payment
},
],
});
Data Pipeline with Quality Gates
Create data pipelines where quality checks must pass: const pipeline = await flowProducer . add ({
name: 'publish-data' ,
queueName: 'publishing' ,
data: {},
children: [
{
name: 'validate-schema' ,
queueName: 'validation' ,
data: {},
opts: { failParentOnFailure: true },
},
{
name: 'quality-check' ,
queueName: 'quality' ,
data: {},
opts: { failParentOnFailure: true },
},
{
name: 'generate-preview' ,
queueName: 'preview' ,
data: {},
// Preview generation is optional
},
],
});
Error Handling
When a parent fails due to a child failure, you can handle it in the parent worker:
import { Worker , UnrecoverableError } from 'bullmq' ;
const parentWorker = new Worker ( 'topQueueName' , async job => {
try {
const childrenValues = await job . getChildrenValues ();
// Process normally if all children succeeded
return processChildren ( childrenValues );
} catch ( error ) {
if ( error instanceof UnrecoverableError ) {
// Check if error message indicates child failure
if ( error . message . includes ( 'child' )) {
console . error ( 'Parent failed due to child failure:' , error . message );
// Perform cleanup or notification
await notifyFailure ( job . data );
}
}
throw error ;
}
});
Combining with Other Options
failParentOnFailure takes precedence over other failure handling options like removeDependencyOnFailure and ignoreDependencyOnFailure. If a child has failParentOnFailure: true, the parent will fail regardless of other options.
You can combine different strategies for different children:
const flow = await flowProducer . add ({
name: 'complex-workflow' ,
queueName: 'workflow' ,
data: {},
children: [
{
name: 'critical-task' ,
queueName: 'tasks' ,
data: {},
opts: { failParentOnFailure: true }, // Parent must fail if this fails
},
{
name: 'optional-task' ,
queueName: 'tasks' ,
data: {},
opts: { ignoreDependencyOnFailure: true }, // Parent can ignore this failure
},
{
name: 'best-effort-task' ,
queueName: 'tasks' ,
data: {},
opts: { removeDependencyOnFailure: true }, // Remove from dependencies if fails
},
],
});
Monitoring Failed Parents
You can monitor and handle parent failures:
import { Queue , QueueEvents } from 'bullmq' ;
const queue = new Queue ( 'topQueueName' , { connection });
const queueEvents = new QueueEvents ( 'topQueueName' , { connection });
queueEvents . on ( 'failed' , async ({ jobId , failedReason }) => {
const job = await queue . getJob ( jobId );
if ( failedReason . includes ( 'child' )) {
console . log ( `Parent job ${ jobId } failed due to child failure` );
// Get information about failed children
const dependencies = await job . getDependencies ({
failed: { count: 100 },
});
console . log ( 'Failed children:' , dependencies . failed );
}
});
API Reference