Stirling-Tools/Stirling-PDF · info · Error

Operation was cancelled

Error message

Operation was cancelled

What it means

Thrown in the per-file processing loop when `axios.isCancel(error)` is true — i.e. the request was aborted via the operation's cancelToken. This is not a backend failure; it is an intentional cancellation (user clicked Cancel, or the component holding the token unmounted). The original Cancel is preserved on `cause`.

Source

Thrown at frontend/editor/src/core/hooks/tools/shared/useToolApiCalls.ts:108

            });
            failedFiles.push(file.name);
            try {
              markFileError?.(file.fileId);
            } catch (e) {
              console.debug("markFileError", e);
            }
            continue;
          }
          processedFiles.push(...responseFiles);
          // record source id as successful
          successSourceIds.push(file.fileId);
          console.debug("[processFiles] Success", {
            name: file.name,
            produced: responseFiles.length,
          });
        } catch (error) {
          if (axios.isCancel(error)) {
            throw new Error("Operation was cancelled", { cause: error });
          }
          console.error("[processFiles] Failed", { name: file.name, error });
          failedFiles.push(file.name);
          // mark errored file so UI can highlight
          try {
            markFileError?.(file.fileId);
          } catch (e) {
            console.debug("markFileError", e);
          }
        }
      }

      if (failedFiles.length > 0 && processedFiles.length === 0) {
        throw new Error(
          `Failed to process all files: ${failedFiles.join(", ")}`,
        );
      }

View on GitHub (pinned to 9ef20dcab8)

Solutions

  1. Treat cancellation as expected control flow: catch it and stop without surfacing an error toast.
  2. Ensure cancelOperation is wired to UI cancel affordances and called on component unmount via useEffect cleanup.
  3. If cancellation fires unexpectedly, audit for accidental double-invocation of cancelToken.cancel (e.g. a stale ref).
  4. Do not retry cancelled operations automatically — cancellation is user intent.

Example fix

// before
if (axios.isCancel(error)) {
  throw new Error("Operation was cancelled", { cause: error });
}

// after — propagate a distinct, non-error signal the UI can treat as expected
if (axios.isCancel(error)) {
  const cancelErr = new Error("Operation was cancelled", { cause: error });
  cancelErr.name = "CancelledError";
  throw cancelErr;
}
// caller:
} catch (e) {
  if (e instanceof Error && e.name === "CancelledError") { onStatus("Cancelled"); return; }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Do not invoke if the operation is already cancelled
if (cancelTokenRef.current?.token.reason) {
  // skip the call; the user already cancelled
}

Type guard

function isCancelledError(e: unknown): boolean {
  return e instanceof Error && e.message === "Operation was cancelled";
}

Try / catch

} catch (e) {
  if (e instanceof Error && (e.message === "Operation was cancelled" || axios.isCancel((e as { cause?: unknown }).cause))) {
    // expected control flow — stop without an error toast
    onStatus("Cancelled");
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: User clicks the Cancel button on a long-running operation (cancelOperation cancels cancelTokenRef.current.token); the component unmounts mid-operation and the parent cancels; an automation chain cancels a step.

Common situations: Cancelling a large multi-file compress/split; navigating away from the tool view while a batch is running; cancelling an automation step.

Related errors


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