Stirling-Tools/Stirling-PDF · error · Error
view.error || policy run ${view.status.toLowerCase()}
Error message
view.error || policy run ${view.status.toLowerCase()} What it means
Thrown by runToCompletion when getPolicyRun returns a status of FAILED or CANCELLED. The message is view.error if the backend supplied one, otherwise a synthesized 'policy run failed'/'policy run cancelled' from the lowercased status. This is the backend reporting the policy pipeline itself failed or was cancelled mid-run (as opposed to a transport error, which is swallowed and retried in the getPolicyRun try/catch).
Source
Thrown at frontend/editor/src/proprietary/services/policyExport.ts:110
await delay(POLL_MS);
let view;
try {
view = await getPolicyRun(runId);
} catch {
continue; // transient — keep polling within the cap.
}
if (view.status === "COMPLETED") {
const out = view.outputs?.[0];
if (!out) throw new Error("policy produced no output");
const blob = await downloadPolicyOutput(out.fileId, target);
// Keep the export's filename; only the bytes are the enforced result.
const enforced = new File([blob], file.name, {
type: blob.type || file.type || "application/pdf",
});
return { file: enforced, runId, target, outputs: view.outputs ?? [] };
}
if (view.status === "FAILED" || view.status === "CANCELLED") {
throw new Error(view.error || `policy run ${view.status.toLowerCase()}`);
}
if (view.status === "WAITING_FOR_INPUT") {
throw new Error(
"policy requires interactive input and cannot run automatically",
);
}
}
throw new Error("policy run timed out");
}
function enforcedFilesSummary(names: string[]): string {
if (names.length === 1) return names[0];
if (names.length === 2)
return i18n.t("policies.enforcement.summaryTwo", {
first: names[0],
second: names[1],
});
return i18n.t("policies.enforcement.summaryMore", {View on GitHub (pinned to 9ef20dcab8)
Solutions
- Read view.error (surfaced in the thrown message) for the backend's failure reason — it usually names the failing step.
- Open the policy run detail in the UI (runId) for the full step-level error log.
- If the input file is corrupt/password-protected, validate it before enforcing or exclude such files from the policy scope.
- Confirm the automation's referenced tools/scripts still exist and are healthy on the backend.
- The export wrapper catches this and falls back to exporting the original file with a warning toast; log the runId for post-hoc review.
Example fix
// before
if (view.status === "FAILED" || view.status === "CANCELLED") {
throw new Error(view.error || `policy run ${view.status.toLowerCase()}`);
}
// after — preserve the error but tag it so callers can distinguish
if (view.status === "FAILED" || view.status === "CANCELLED") {
const msg = view.error || `policy run ${view.status.toLowerCase()}`;
const e = new Error(msg);
(e as any).policyRunId = runId;
(e as any).policyStatus = view.status;
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-validate input file health to avoid backend FAILED on corrupt PDFs
if (!isPdf(file) || await isEncryptedPdf(file)) {
skipEnforcement(file, 'unsupported input');
} Type guard
export function isPolicyRunFailure(e: unknown): e is Error {
return e instanceof Error && /policy run (failed|cancelled)|policy produced|timed out|interactive input/i.test(e.message);
} Try / catch
// export wrapper treats this as non-fatal: export the original + warn
try {
enforced = await runToCompletion(backendId, file);
} catch (e) {
if (isPolicyRunFailure(e)) {
warnExportWithOriginal(file, e);
enforced = { file, runId: undefined, target, outputs: [] };
} else throw e;
} Prevention
- Validate input PDFs (not corrupt, not encrypted) before enforcing a policy on them.
- Keep the automation's referenced tools/scripts present and healthy on the backend.
- Log the runId from the thrown error so backend step-level failures can be investigated.
- Treat FAILED/CANCELLED as expected during export and fall back to the original file with a user-visible warning.
When it happens
Trigger: A pipeline operation threw on the backend (e.g. a conversion failed on a corrupt PDF); the policy automation references a missing tool/script; an admin or system event cancelled the run; the run exceeded backend resource limits and was marked FAILED; the input file triggered a guard the policy enforces.
Common situations: Policy automation points at a tool that was removed in a release; the source PDF is corrupt or password-protected and a step can't process it; backend PDF engine (LibreOffice) crashed on the input; user cancelled from the runs UI; backend OOM killed the run.
Related errors
- policy produced no output
- Unknown policy category: ${id}
- Supabase is not configured
- Failed to submit signature
- Failed to decline
AI-assisted analysis of Stirling-Tools/Stirling-PDF@9ef20dcab8 (2026-08-13).
Data as JSON: /api/errors/7c3fe7d1e235a46d.
Report an issue: GitHub.