Stirling-Tools/Stirling-PDF · error · Error

Automation step failed

Error message

Automation step ${stepIndex + 1} failed: ${error}

What it means

Thrown from the per-step error callback passed to `executeAutomationSequence`. When any step in the automation chain fails, the executor invokes onStepError with the index and error string; this callback rethrows so the overall automation aborts and surfaces which step broke. The error string is whatever the failed step (a downstream tool operation) reported.

Solutions

  1. Inspect the originating step's own error (it is carried in the `${error}` fragment) and fix the root cause there.
  2. Make automation steps resilient: validate each step's output before passing it downstream.
  3. Add per-step retry with backoff for transient (network/5xx) errors so a single flaky step does not abort the whole run.
  4. Log the full AutomationStep + params at onStepError for debugging which configuration is at fault.

Example fix

// before
(stepIndex: number, error: string) => {
  console.error(`Step ${stepIndex + 1} failed:`, error);
  params.onStepError?.(stepIndex, error);
  throw new Error(`Automation step ${stepIndex + 1} failed: ${error}`);
},

// after — keep cause and step identity for richer debugging
(stepIndex: number, error: string) => {
  console.error(`Step ${stepIndex + 1} failed:`, error);
  params.onStepError?.(stepIndex, error);
  throw new Error(`Automation step ${stepIndex + 1} failed: ${error}`, { cause: error });
},
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate each step's config + output compatibility before running the chain
for (const step of params.automationConfig.steps) {
  if (!toolRegistry[step.operation]) {
    // surface 'step N references unknown operation' before running
  }
}

Try / catch

try {
  await runAutomation();
} catch (e) {
  const m = e instanceof Error && e.message.match(/Automation step (\d+) failed: (.+)/);
  if (m) {
    const [, step, reason] = m;
    toast.error(`Step ${step} failed: ${reason}`);
  } else throw e;
}

Prevention

When it happens

Trigger: A downstream tool in the chain threw (e.g. convert got 'Unsupported conversion format', compress hit a network error, split returned no files); a step received a file format it cannot handle; a step's API call failed (5xx / timeout); a step produced zero output files and the executor treats that as failure.

Common situations: Multi-step automations where an earlier step's output is incompatible with a later step; backend intermittently failing one endpoint in the chain; a step referencing a tool not present in the registry.

Related errors


AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13). Data as JSON: /api/errors/097636c438921724. Report an issue: GitHub.

Appendix: source

Thrown at frontend/editor/src/core/hooks/tools/automate/useAutomateOperation.ts:43

      // Execute the automation sequence and return the final results
      const finalResults = await executeAutomationSequence(
        params.automationConfig!,
        files,
        toolRegistry,
        (stepIndex: number, operationName: string) => {
          console.log(`Step ${stepIndex + 1} started: ${operationName}`);
          params.onStepStart?.(stepIndex, operationName);
        },
        (stepIndex: number, resultFiles: File[]) => {
          console.log(
            `Step ${stepIndex + 1} completed with ${resultFiles.length} files`,
          );
          params.onStepComplete?.(stepIndex, resultFiles);
        },
        (stepIndex: number, error: string) => {
          console.error(`Step ${stepIndex + 1} failed:`, error);
          params.onStepError?.(stepIndex, error);
          throw new Error(`Automation step ${stepIndex + 1} failed: ${error}`);
        },
      );

      console.log(
        `✅ Automation completed, returning ${finalResults.length} files`,
      );
      return {
        files: finalResults,
        consumedAllInputs: true,
      };
    },
    [toolRegistry],
  );

  return useToolOperation<AutomateParameters>(
    defineCustomTool({
      operationType: "automate",
      customProcessor,

View on GitHub (pinned to 9ef20dcab8)