NousResearch/hermes-agent · warning · Error
Invalid PDF data URL payload
Error message
Invalid PDF data URL payload
What it means
Third guard in dataUrlToBlob: after metadata validation it runs decodeURIComponent then atob on the payload. A throw here means the payload is not decodable base64 — stray whitespace/newlines from line-wrapped output, URL-unsafe characters, percent-decoding that left invalid base64, or a truncated transfer. The error cleanly separates 'bad encoding' from 'wrong content' (the next guard checks the %PDF- header).
Source
Thrown at apps/desktop/src/app/chat/right-rail/preview-file.tsx:245
}
const metadata = dataUrl
.slice(5, comma)
.split(';')
.map(part => part.trim().toLowerCase())
const payload = dataUrl.slice(comma + 1)
if (metadata[0] !== 'application/pdf' || !metadata.slice(1).includes('base64')) {
throw new Error('Invalid PDF data URL type')
}
let binary: string
try {
binary = atob(decodeURIComponent(payload))
} catch {
throw new Error('Invalid PDF data URL payload')
}
if (!binary.startsWith('%PDF-')) {
throw new Error('Invalid PDF file header')
}
const bytes = new Uint8Array(binary.length)
for (let index = 0; index < binary.length; index += 1) {
bytes[index] = binary.charCodeAt(index)
}
return new Blob([bytes], { type: 'application/pdf' })
}
async function readTextPreview(filePath: string) {
try {
return await readDesktopFileText(filePath)View on GitHub (pinned to c896c09c42)
Solutions
- Strip whitespace and normalize base64url (-_ to +/, add '=') before decoding.
- Re-transfer the PDF — if the payload is truncated, only the source can supply the complete string.
- Fix the producer to emit canonical base64 with padding.
- For huge PDFs prefer a temp file / IPC path instead of data URLs, which hit URL-length and encoding limits.
Example fix
// before
try {
binary = atob(decodeURIComponent(payload))
} catch {
throw new Error('Invalid PDF data URL payload')
}
// after
try {
const normalized = payload.replace(/\s+/g, '').replace(/-/g, '+').replace(/_/g, '/')
const padded = normalized + '='.repeat((4 - (normalized.length % 4)) % 4)
binary = atob(decodeURIComponent(padded))
} catch {
throw new Error('Invalid PDF data URL payload')
} Defensive patterns
Strategy: validation
Validate before calling
const normalizedBase64 = (payload: string) => {
const clean = payload.replace(/\s+/g, '').replace(/-/g, '+').replace(/_/g, '/')
return clean + '='.repeat((4 - (clean.length % 4)) % 4)
}
// pre-validate before calling dataUrlToBlob
if (!/^[A-Za-z0-9+/]*={0,2}$/.test(normalizedBase64(payload))) throw new Error('payload is not base64') Type guard
const isCanonicalBase64 = (s: string): boolean =>
/^[A-Za-z0-9+/]+={0,2}$/.test(s.replace(/\s+/g, '')) Try / catch
try { blob = dataUrlToBlob(url) } catch (e) { if (e.message === 'Invalid PDF data URL payload') { /* retry once with normalized base64url->base64 */ } } Prevention
- Normalize base64 (strip whitespace, map base64url alphabet, restore padding) before decode
- Avoid data URLs for large documents; use temp files or IPC
- Verify payload length % 4 == 0 before atob
When it happens
Trigger: Base64 with embedded newlines (MIME-style line wrapping), missing padding, '+/' converted to '-_' (base64url), or payload truncated mid-stream so atob cannot parse it.
Common situations: PDFs relayed through systems that wrap or re-encode base64 (email gateways, JSON pretty-print, log copy-paste); producers using base64url; clipboard truncation of very large data URLs.
Related errors
- Invalid PDF data URL
- Invalid PDF file header
- Invalid PDF data URL type
- Branch name is required.
- Missing URL
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/afecc204585498e9.
Report an issue: GitHub.