{"record":{"id":"0ddddf3b501eee9d","repo":"amruthpillai/reactive-resume","slug":"application-documents-must-be-pdf-files","errorCode":null,"errorMessage":"Application documents must be PDF files.","messagePattern":"Application documents must be PDF files\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/mcp/src/tools.ts","lineNumber":64,"sourceCode":"\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tisError: true,\n\t\t\t\tcontent: [{ type: \"text\", text: `Error ${label}: ${errorMessage(error)}${errorHint(error)}` }],\n\t\t\t};\n\t\t}\n\t};\n}\n\nfunction text(value: string): CallToolResult {\n\treturn { content: [{ type: \"text\", text: value }] };\n}\n\nfunction json(value: unknown): CallToolResult {\n\treturn text(JSON.stringify(value, null, 2));\n}\n\nfunction fileFromBase64(input: { fileName: string; contentType: string; dataBase64: string }): File {\n\tif (input.contentType !== \"application/pdf\") throw new Error(\"Application documents must be PDF files.\");\n\n\tconst bytes = Buffer.from(input.dataBase64, \"base64\");\n\tif (bytes.length === 0) throw new Error(\"Application document cannot be empty.\");\n\n\treturn new File([bytes], input.fileName, { type: input.contentType });\n}\n\nfunction coerceFollowUpAt(input: Record<string, unknown>): Record<string, unknown> {\n\tif (!(\"followUpAt\" in input)) return input;\n\n\tconst followUpAt = input.followUpAt;\n\tif (followUpAt === undefined || followUpAt === null || followUpAt instanceof Date) return input;\n\n\treturn { ...input, followUpAt: new Date(String(followUpAt)) };\n}\n\nfunction buildResumeShareUrl(username: string, slug: string): string {\n\tconst base = env.APP_URL.replace(/\\/$/, \"\");","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/amruthpillai/reactive-resume/blob/3a5b12e2a40374a9571988701fcb75c5a1831c42/packages/mcp/src/tools.ts#L46-L82","documentation":"fileFromBase64 enforces that application documents submitted through an MCP tool are PDFs: it throws if input.contentType !== 'application/pdf'. This is a hard format gate for cover-letter / application-document upload tooling before constructing the File used downstream.","triggerScenarios":"An MCP tool call submits a document with contentType 'application/msword', 'image/png', 'text/plain', or an empty/wrong MIME; the caller guessed the content type instead of reading it from the file.","commonSituations":"Automation that re-uses a generic MIME for any document; a client that doesn't detect the file type; a DOC converted to PDF but mislabeled.","solutions":["Convert the source document to PDF before submission and set contentType: 'application/pdf'.","If you only have bytes, sniff the magic bytes (%PDF-) and set contentType accordingly, or reject early client-side.","Ensure the fileName also ends in .pdf to avoid downstream content-type inference mismatches."],"exampleFix":"// before\n{ fileName: 'cover.docx', contentType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', dataBase64 }\n// after (convert to PDF first)\n{ fileName: 'cover.pdf', contentType: 'application/pdf', dataBase64: pdfBase64 }","handlingStrategy":"validation","validationCode":"if (input.contentType !== 'application/pdf') {\n  throw new TypeError('Application documents must be PDF; convert the file first.');\n}","typeGuard":"function isPdfInput(i: { contentType: string }): boolean {\n  return i.contentType === 'application/pdf';\n}","tryCatchPattern":null,"preventionTips":["Convert source documents to PDF before submission.","Set fileName with a .pdf extension to match.","Sniff %PDF- magic bytes when MIME is unknown."],"tags":["mcp","validation","pdf","attachments","content-type"],"backgroundTag":null,"analyzedSha":"3a5b12e2a40374a9571988701fcb75c5a1831c42","analyzedAt":"2026-08-12T22:31:22.666Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}