{"record":{"id":"1c411ca91bf239ad","repo":"NousResearch/hermes-agent","slug":"invalid-pdf-data-url-type","errorCode":null,"errorMessage":"Invalid PDF data URL type","messagePattern":"Invalid PDF data URL type","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"apps/desktop/src/app/chat/right-rail/preview-file.tsx","lineNumber":237,"sourceCode":"  return suspicious / Math.min(bytes.length, 4096) > 0.12\n}\n\nfunction dataUrlToBlob(dataUrl: string) {\n  const comma = dataUrl.indexOf(',')\n\n  if (comma < 0 || !dataUrl.startsWith('data:')) {\n    throw new Error('Invalid PDF data URL')\n  }\n\n  const metadata = dataUrl\n    .slice(5, comma)\n    .split(';')\n    .map(part => part.trim().toLowerCase())\n\n  const payload = dataUrl.slice(comma + 1)\n\n  if (metadata[0] !== 'application/pdf' || !metadata.slice(1).includes('base64')) {\n    throw new Error('Invalid PDF data URL type')\n  }\n\n  let binary: string\n\n  try {\n    binary = atob(decodeURIComponent(payload))\n  } catch {\n    throw new Error('Invalid PDF data URL payload')\n  }\n\n  if (!binary.startsWith('%PDF-')) {\n    throw new Error('Invalid PDF file header')\n  }\n\n  const bytes = new Uint8Array(binary.length)\n\n  for (let index = 0; index < binary.length; index += 1) {\n    bytes[index] = binary.charCodeAt(index)","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/src/app/chat/right-rail/preview-file.tsx#L219-L255","documentation":"Second guard in dataUrlToBlob: the metadata segment between 'data:' and the comma must declare media type 'application/pdf' and include a 'base64' parameter (case-insensitive after trimming). This error means the data URL is structurally valid but is not a base64-encoded PDF — e.g. an image/png data URL, a text/plain payload, or a PDF encoded without the base64 marker.","triggerScenarios":"Passing a data URL whose MIME is image/*, text/*, or application/octet-stream into the PDF preview; a producer that emitted 'data:pdf;base64' (non-standard type) or omitted ';base64' and inlined raw bytes.","commonSituations":"Attachment kind detection guessing 'pdf' from a .pdf-ish filename while the actual payload is a PNG screenshot; generic preview code funnelling every data URL through the PDF converter; upstream models/tools emitting non-standard MIME tokens.","solutions":["Detect the MIME from the data URL itself and dispatch to the matching preview (image viewer for image/*, text for text/*) instead of assuming PDF.","Fix the payload producer to emit `data:application/pdf;base64,...` exactly.","If the PDF arrives without base64 (raw percent-encoded), add an encoding branch instead of loosening this check.","Validate attachment metadata against the actual data URL header before opening the preview."],"exampleFix":"// before\nif (metadata[0] !== 'application/pdf' || !metadata.slice(1).includes('base64')) {\n  throw new Error('Invalid PDF data URL type')\n}\n\n// after — accept the alias some producers emit, keep the contract strict\nconst mime = metadata[0] === 'pdf' ? 'application/pdf' : metadata[0]\nif (mime !== 'application/pdf' || !metadata.slice(1).includes('base64')) {\n  throw new Error('Invalid PDF data URL type')\n}","handlingStrategy":"type-guard","validationCode":"const mime = dataUrl.slice(5, dataUrl.indexOf(','))\nconst kind = mime.split(';')[0]\nswitch (kind) {\n  case 'application/pdf': openPdfPreview(dataUrl); break\n  case 'image/png': case 'image/jpeg': openImagePreview(dataUrl); break\n  default: openTextPreview(dataUrl)\n}","typeGuard":"const isPdfDataUrl = (s: string): boolean => /^data:application\\/pdf;base64,/i.test(s)","tryCatchPattern":"try { blob = dataUrlToBlob(url) } catch (e) { /* check message === 'Invalid PDF data URL type' -> route by MIME to another previewer */ }","preventionTips":["Derive preview type from the data URL MIME segment, not the filename","Fix producers to emit exactly data:application/pdf;base64,","Test with image/* and text/* data URLs to prove dispatch works"],"tags":["desktop","preview","pdf","data-url","mime-type"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}