World’s largest virtual agentic engineering & quality conference
Make gives you a transactional execution model and five error-handler directives. Here is how to test scenarios with them, from Run Once through router coverage to production monitoring.

Himanshu Sheth
Author

Saurabh Prakash
Reviewer
Last Updated on: August 20, 2026
Make documents five error-handler directives on its error handlers documentation: Skip, Retry, Resume, Commit, and Rollback.
Each of those names an outcome you can choose when a module fails. Leave that choice unmade and you have not avoided a decision, you have accepted a default one, and no test in your scenario asserts what it is.
That gap is the opportunity. Make's execution model is genuinely more testable than most workflow tools give you, because it lets you specify what should happen when a step fails, per module. This guide covers how to test against that model: what Run Once actually proves, how bundles flow, which directive to attach where, and how to catch the failures that never raise an error.
TL;DR
Run Once is the best debugging affordance in the category. It executes the scenario against live data and then lets you open every module and inspect the exact bundles that went in and came out. For understanding data shape, nothing beats it.
It still only proves one thing: this scenario worked once, for this bundle, on this data. Three gaps follow from that:
Use it as the inspection tool it is, then build deliberate coverage around it. The same distinction between a wiring check and a real suite drives our companion guide to Zapier testing, where the platform gives you noticeably less to assert against. On a code-first platform the balance flips the other way, which is what Pipedream testing covers.
Testing Make well requires knowing what a run is made of. Per Make's scenario execution flow documentation, a bundle is the data a module returns, and each bundle moves through a four-phase transaction: initialization, operation, commit or rollback, and finalization.
The detail that matters most for testing is sequencing. That same documentation states that modules process bundles one at a time rather than in parallel, so a second bundle does not begin until the first has finished traversing the scenario.
Three testing consequences follow directly:
An error handler is a route you attach to a module that runs instead of the failure. The directive at the end of that route decides what happens to the run. Make's error handlers documentation defines five, and the distinctions between them are the whole substance of Make.com testing.
| Directive | What Make says it does | Run continues? | Test to write |
|---|---|---|---|
| Skip | Disregard errors and allow the scenario to process subsequent bundles | Yes | Poison record mid-batch; assert later bundles still processed. |
| Retry | Store incomplete executions and enable automatic or manual retries | No | Force a transient failure; assert an incomplete execution appears. |
| Resume | Set a substitute value for a failed module and continue scenario processing | Yes | Assert the substitute value reaches downstream modules intact. |
| Commit | Stop scenario execution when an error occurs and save the processed changes | No | Fail mid-scenario; assert earlier writes survived. |
| Rollback | Stop scenario execution when an error occurs and revert changes | No | Fail mid-scenario; assert earlier writes were reverted. |
Retry is the only directive that stores an incomplete execution. If your recovery plan depends on replaying failed runs later, any other directive silently discards them.
The choice is a decision you should be able to defend per module, so it is worth writing down as testable logic before you configure anything. Modelling the documented semantics makes the trade-offs explicit:
import test from 'node:test';
import assert from 'node:assert/strict';
// Make's five documented directives, modelled so a suite can assert which one
// a scenario branch should carry before you wire it up in the editor.
const DIRECTIVES = {
skip: { continuesScenario: true, keepsChanges: true, storesIncomplete: false },
retry: { continuesScenario: false, keepsChanges: true, storesIncomplete: true },
resume: { continuesScenario: true, keepsChanges: true, storesIncomplete: false },
commit: { continuesScenario: false, keepsChanges: true, storesIncomplete: false },
rollback: { continuesScenario: false, keepsChanges: false, storesIncomplete: false },
};
export function chooseDirective({ sideEffectsAlreadyWritten, canSubstituteValue, errorIsTransient }) {
if (errorIsTransient) return 'retry';
if (canSubstituteValue) return 'resume';
if (sideEffectsAlreadyWritten) return 'commit';
return 'rollback';
}
export function simulate(directive, remainingBundles) {
const d = DIRECTIVES[directive];
if (!d) throw new Error(`unknown directive "${directive}"`);
return {
bundlesProcessedAfterError: d.continuesScenario ? remainingBundles : 0,
changesPersisted: d.keepsChanges,
incompleteExecutionStored: d.storesIncomplete,
};
}
test('retry is the only directive that stores an incomplete execution', () => {
const stored = Object.entries(DIRECTIVES).filter(([, d]) => d.storesIncomplete).map(([n]) => n);
assert.deepEqual(stored, ['retry']);
});
test('commit and rollback differ only in whether changes survive', () => {
assert.equal(simulate('commit', 3).changesPersisted, true);
assert.equal(simulate('rollback', 3).changesPersisted, false);
assert.equal(simulate('commit', 3).bundlesProcessedAfterError, 0);
assert.equal(simulate('rollback', 3).bundlesProcessedAfterError, 0);
});
test('a half-written invoice must not silently roll back', () => {
const d = chooseDirective({
sideEffectsAlreadyWritten: true, canSubstituteValue: false, errorIsTransient: false,
});
assert.equal(d, 'commit');
});Running the full file, which also covers Skip's batch behavior and transient-error routing, gives this actual output:
$ node --test make-directives.test.mjs
1..6
# tests 6
# pass 6
# fail 0
# duration_ms 139.5568Six assertions in 139 milliseconds, with no Make account involved. This models Make's documented semantics rather than executing a scenario, so treat it as a design check: it forces the per-module decision to be explicit and reviewable before anyone configures a handler in the editor.
A router turns one scenario into several. Coverage collapses fastest here, because a run that takes one route tells you nothing about the others.
Write the expected route beside each seeded record before running. Deciding afterwards which route "looks right" is how a mis-ordered filter gets rationalized as correct.
Incomplete executions are Make's recovery queue. Per the directive definitions above, only Retry creates them: failed runs are stored so they can be retried automatically or manually once the underlying problem is fixed.
Teams treat that queue as a safety net, which it is, and then stop there, which is the mistake. A queue nobody watches is a data-loss backlog with extra steps. Two habits fix it:
Note: Workflow runs and test runs degrade the same way: a growing pile of retries that nobody reads until something visible breaks. TestMu AI surfaces failure patterns across runs so the trend is obvious before the outage. Try TestMu AI free!
A Make scenario is marked successful once all bundles traverse every module without erroring. Success is a statement about traversal, not about correctness. When an upstream app renames a field, the mapping resolves to empty, every module completes, and the run is green.
Three checks catch what the status never will:
The reasoning generalizes past Make. A green trend is only as trustworthy as the assertions that turned each run green, which is exactly why TestMu AI's Test Insights is built as an observability layer over execution records rather than a verdict generator: it aggregates runs into failure-frequency analysis, error-message clustering, and stability trends so a suite that is degrading rather than failing becomes visible. It reads the record your assertions produced and cannot make a weakly-asserted record true, which is the same limitation a Make scenario status has. Our guide to preventing flaky tests covers that detection problem in a test suite.
Open your most business-critical scenario and check how many modules carry an error handler. If the answer is none, attach one to every module that writes data and decide its directive deliberately: Retry for transient failures, Resume where a substitute value is safe, Commit where a partial write must stand, Rollback where it must not. That single pass converts silent, total run failure into a handled outcome you chose.
Then add the shape assertion after your trigger and a baseline alert on operation counts, because those two catch the failures no directive can. If the same workflow automation also drives your release process, our walkthrough of automated cross-browser smoke checks from n8n shows the pattern for making an automation platform run tests rather than only move data.
Author
Himanshu Sheth is the Director of Marketing (Technical Content) at TestMu AI, with over 8 years of hands-on experience in Selenium, Cypress, and other test automation frameworks. He has authored more than 130 technical blogs for TestMu AI, covering software testing, automation strategy, and CI/CD. At TestMu AI, he leads the technical content efforts across blogs, YouTube, and social media, while closely collaborating with contributors to enhance content quality and product feedback loops. He has done his graduation with a B.E. in Computer Engineering from Mumbai University. Before TestMu AI, Himanshu led engineering teams in embedded software domains at companies like Samsung Research, Motorola, and NXP Semiconductors. He is a core member of DZone and has been a speaker at several unconferences focused on technical writing and software quality.
Reviewer
Saurabh Prakash is an Engineering Manager at TestMu AI (formerly LambdaTest), where he leads engineering on agentic AI development and scalable system architecture for the quality engineering platform. He has also contributed to Test at Scale, the company's open-source test intelligence platform. He brings over 9 years of experience across Node.js, Java, Spring, MVC, data structures, algorithms, and scalable system design, with earlier roles as SDE 2 at Zomato, Senior Software Engineer at LogicHub, and Software Development Engineer at Directi. Saurabh holds a B.Tech in Computer Science and Engineering from Delhi Technological University.
Did you find this page helpful?
More Related Blogs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance