amruthpillai/reactive-resume · error · ORPCError
NOT_FOUND
NOT_FOUND
Error message
No cover letter found for this resume
What it means
createResumePdfDownload() throws NOT_FOUND when target is 'cover-letter' but resumeHasCoverLetter(data) is false. The cover letter is an optional resume section; exporting it requires the resume to actually contain one. The check runs after loading the resume but before invoking the PDF renderer.
Source
Thrown at packages/api/src/features/resume/export.ts:28
export {
createResumePdfDownloadUrl,
MAX_PDF_DOWNLOAD_URL_TTL_SECONDS,
verifyResumePdfDownloadToken,
} from "./pdf-download-url";
type CreateResumePdfDownloadInput = {
id: string;
userId: string;
target?: ResumeExportTarget;
};
export async function createResumePdfDownload(input: CreateResumePdfDownloadInput) {
const resume = await resumeService.getById({ id: input.id, userId: input.userId });
const data = parseStoredResumeData(resume.data);
const target = input.target ?? "resume";
if (target === "cover-letter" && !resumeHasCoverLetter(data)) {
throw new ORPCError("NOT_FOUND", { message: "No cover letter found for this resume" });
}
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,
};View on GitHub (pinned to 3a5b12e2a4)
Solutions
- Call resumeHasCoverLetter(data) (or check data.sections.summary.coverLetter) before offering the cover-letter export.
- Gate the UI option behind presence of the section.
- Default target to 'resume' when no cover letter exists.
Example fix
// before
downloadResumePdf({ id, target: 'cover-letter' });
// after
const has = resumeHasCoverLetter(resumeData);
downloadResumePdf({ id, target: has ? 'cover-letter' : 'resume' }); Defensive patterns
Strategy: validation
Validate before calling
import { resumeHasCoverLetter } from '@reactive-resume/resume/export-sections';
const target = input.target === 'cover-letter' && resumeHasCoverLetter(data) ? 'cover-letter' : 'resume'; Type guard
function hasCoverLetter(data): boolean {
return Boolean(data?.sections?.summary?.coverLetter);
} Try / catch
try {
await downloadResumePdf({ id, target: 'cover-letter' });
} catch (e) {
if (e.code === 'NOT_FOUND') { /* fall back to resume export */ await downloadResumePdf({ id, target: 'resume' }); }
else throw e;
} Prevention
- Gate the 'download cover letter' action on resumeHasCoverLetter(data).
- Hide the option entirely when the section is absent or empty.
- Default to target 'resume' when in doubt.
When it happens
Trigger: GET /resumes/{id}/pdf?target=cover-letter on a resume whose data has no cover-letter section (or it is empty).
Common situations: A download menu that always offers 'cover letter' regardless of whether the user added one; a fresh template that doesn't include the section; a resume where the section was deleted.
Related errors
- INTERNAL_SERVER_ERROR
- NOT_FOUND
- An unknown error occurred while validating the merged resume
- BAD_REQUEST
- RATE_LIMIT_EXCEEDED
AI-assisted analysis of amruthpillai/reactive-resume@3a5b12e2a4 (2026-08-12).
Data as JSON: /api/errors/d3d933cc245c09d9.
Report an issue: GitHub.