hcengineering/platform · error

Failed to create PDF: ${err.message}

Error message

Failed to create PDF: ${err.message}

What it means

docToPdf converts office documents to PDF using LibreOffice (soffice) with a temporary profile directory. After running the conversion it verifies the expected output file exists via fs access; if the PDF was not produced it throws this error with LibreOffice's stderr/err.message appended. It signals the office-to-PDF conversion pipeline failed.

Source

Thrown at pods/preview/src/utils/libreoffice.ts:92

          reject(new Error(`LibreOffice exited with code ${code}`))
        } else {
          resolve()
        }
      })

      proc.on('error', (err) => {
        ctx.error('LibreOffice failed', { stdout, stderr, docFile, pdfFile })
        reject(new Error(`Failed to start LibreOffice: ${err.message}`))
      })
    })
  } finally {
    await rm(profileDir, { recursive: true })
  }

  try {
    await access(pdfFile)
  } catch (err: any) {
    throw new Error(`Failed to create PDF: ${err.message}`)
  }

  return pdfFile
}

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Verify LibreOffice (soffice) is installed and executable on the host and works headless (soffice --headless --convert-to pdf test.docx).
  2. Check the wrapped err.message/LibreOffice stderr for the specific conversion failure (corrupt file, unsupported format, permissions).
  3. Test the specific document manually with the same soffice command; re-export/re-upload the file if it is corrupt.
  4. Check permissions on the temp/profile directories and available disk space and memory.

Example fix

// before
const pdfFile = await docToPdf(ctx, inputDocPath)
// after
if (!existsSync(inputDocPath) || statSync(inputDocPath).size === 0) {
  throw new Error('source document missing or empty')
}
const pdfFile = await docToPdf(ctx, inputDocPath)
Defensive patterns

Strategy: validation

Validate before calling

import { access, constants } from 'fs/promises'
await access(inputDocPath, constants.R_OK) // source must exist and be readable
if (statSync(inputDocPath).size === 0) throw new Error('empty document')

Type guard

function isConvertibleDoc(contentType: string): boolean {
  return /msword|openxmlformats|opendocument/.test(contentType)
}

Try / catch

try {
  const pdf = await docToPdf(ctx, docPath)
} catch (err) {
  if (/Failed to create PDF/.test(err.message)) {
    ctx.error('libreoffice conversion failed', { cause: err.message, docPath })
    throw new Error('document conversion unavailable')
  }
  throw err
}

Prevention

When it happens

Trigger: Converting a doc/docx/odt (or similar) blob to PDF when soffice is missing, crashes, times out, or rejects the input file — so the output .pdf never appears on disk.

Common situations: Host without LibreOffice installed, HOME/profile-dir permission problems for the soffice process, password-protected or corrupt documents, resource exhaustion (memory/CPU) killing soffice, unsupported legacy formats.

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/1a6085ad289fa4bf. Report an issue: GitHub.