fix(api): return user-safe processing errors, keep raw stderr in logs

Add friendlyError() which collapses raw external-tool failure output (ffmpeg/ffprobe/LibreOffice/qpdf/etc.) into one generic sentence while preserving intentional validation messages and scrubbing internal paths. Apply it at every client-facing error surface in the tool factory and job worker (sync 422, async SSE, pipeline + batch finalize). The full error is still recorded server-side via request.log.error / logger.error and telemetry.
This commit is contained in:
SnapOtter
2026-06-17 14:22:16 +08:00
parent e96c314ab9
commit 4af4bfa8eb
3 changed files with 42 additions and 10 deletions
+5 -2
View File
@@ -10,7 +10,7 @@ import { env } from "../config.js";
import { db, schema } from "../db/index.js";
import { enqueueToolJob, waitForJob } from "../jobs/enqueue.js";
import { trackEvent } from "../lib/analytics.js";
import { formatZodErrors, stripInternalPaths } from "../lib/errors.js";
import { formatZodErrors, friendlyError, stripInternalPaths } from "../lib/errors.js";
import { isToolInstalled } from "../lib/feature-status.js";
import { getObjectBuffer, putObject } from "../lib/object-storage.js";
import { resolveToolPool, shouldSkipSyncWindow } from "../lib/pool.js";
@@ -587,9 +587,12 @@ export function createToolRoute<T>(app: FastifyInstance, config: ToolRouteConfig
error_code: err instanceof Error ? err.constructor.name : "UnknownError",
error_message: err instanceof Error ? err.message.slice(0, 200) : "Processing failed",
});
// Keep the full error (incl. raw ffmpeg/tool stderr) in server logs,
// but return only a user-safe detail to the client.
request.log.error({ err, toolId: config.toolId }, "tool processing failed");
return reply.status(422).send({
error: "Processing failed",
details: stripInternalPaths(err instanceof Error ? err.message : String(err)),
details: friendlyError(err instanceof Error ? err.message : String(err)),
});
}
} finally {