amruthpillai/reactive-resume · error · ORPCError

INTERNAL_SERVER_ERROR

INTERNAL_SERVER_ERROR

Error message

Failed to generate resume PDF

What it means

Catch-all around the lazy-loaded PDF renderer in createResumePdfDownload(). Any error from the dynamic import('@reactive-resume/pdf/server') or createResumePdfFile() is logged with the resumeId and re-thrown as INTERNAL_SERVER_ERROR. The NOT_FOUND at line 28 is thrown before the try block, so it propagates unchanged. The original error is only in server logs, not the response.

Source

Thrown at packages/api/src/features/resume/export.ts:49

	const filename = generateFilename(target === "cover-letter" ? `${resume.name} Cover Letter` : resume.name, "pdf");

	try {
		// Lazy-load the PDF renderer (@reactive-resume/pdf → @react-pdf/renderer +
		// phosphor-icons-react-pdf, ~10.6k icon modules) only when a PDF is actually
		// exported, instead of at server boot. Slashes cold-start file I/O on
		// constrained/slow-disk hosts. See fork perf/lazy-load-pdf.
		const { createResumePdfFile } = await import("@reactive-resume/pdf/server");
		const body = await createResumePdfFile({ data: getResumeExportData(data, target), filename });

		return {
			headers: {
				"content-disposition": `attachment; filename="${filename}"`,
			},
			body,
		};
	} catch (error) {
		console.error("[PDF API] Failed to render resume PDF", { resumeId: input.id, error });
		throw new ORPCError("INTERNAL_SERVER_ERROR", { message: "Failed to generate resume PDF" });
	}
}

export const downloadResumePdfProcedure = protectedProcedure
	.route({
		method: "GET",
		path: "/resumes/{id}/pdf",
		tags: ["Resumes"],
		operationId: "downloadResumePdf",
		summary: "Download resume as PDF",
		description:
			"Generates a PDF for the specified resume and returns it as a forced download. Only resumes belonging to the authenticated user can be downloaded. Requires authentication.",
		successDescription: "The generated resume PDF.",
		outputStructure: "detailed",
	})
	.input(
		z.object({
			id: z.string().describe("The ID of the resume."),

View on GitHub (pinned to 3a5b12e2a4)

Solutions

  1. Inspect server logs for the '[PDF API] Failed to render resume PDF' line — it carries the underlying error.
  2. Validate image URLs and font paths in the resume data before exporting.
  3. Reproduce locally by calling createResumePdfFile({data, filename}) directly to get the raw error.
  4. Increase container memory if rendering large or multi-page resumes.
Defensive patterns

Strategy: try-catch

Validate before calling

function validateResumeAssets(data) {
  const urls = [];
  for (const url of urls) { try { new URL(url); } catch { throw new Error(`Bad image URL: ${url}`); } }
}

Try / catch

try {
  await createResumePdfDownload({ id, userId });
} catch (e) {
  if (e.code === 'INTERNAL_SERVER_ERROR') {
    // surface a generic 'export failed' message; the cause is in server logs
    console.error('PDF export failed for', id);
  } else throw e;
}

Prevention

When it happens

Trigger: Font registration failure, a React-PDF render error (malformed node, unreachable image URL), out-of-memory on large resumes, a broken template, or the pdf package failing to load.

Common situations: A resume referencing a remote image that 404s, a corrupted font file, a template bug after a package upgrade, or insufficient container memory.

Related errors


AI-assisted analysis of amruthpillai/reactive-resume@3a5b12e2a4 (2026-08-12). Data as JSON: /api/errors/1cfb32b8b39ecefa. Report an issue: GitHub.