hcengineering/platform · error · ApiError

Failed to convert

Error message

Failed to convert

What it means

convertToHtml returned undefined, meaning the DOCX→HTML conversion library failed to produce output for the given buffer. The service raises this 400 ApiError rather than caching or returning an empty conversion. The specific parser failure is only visible in service logs.

Source

Thrown at services/print/pod-print/src/server.ts:271

      if (!convertableFormats.includes(stat.contentType)) {
        throw new ApiError(400, `File of this type (${stat.contentType}) cannot be converted`)
      }

      const convertId = getConvertId(file, stat.etag)
      const convertStats = await storageAdapter.stat(ctx, wsUuid, convertId)

      if (convertStats === undefined) {
        const originalFile = await storageAdapter.read(ctx, wsUuid, file)

        if (originalFile === undefined) {
          throw new ApiError(404, `File ${file} not found`)
        }

        const htmlRes = await ctx.with('convertToHtml', {}, () => convertToHtml(Buffer.concat(originalFile as any)))

        if (htmlRes === undefined) {
          throw new ApiError(400, 'Failed to convert')
        }

        const htmlBuf = Buffer.from(htmlRes)

        await storageAdapter.put(ctx, wsUuid, convertId, htmlBuf, 'text/html', htmlBuf.length)
      }

      res.contentType('application/json')
      res.send({ id: convertId })
    })
  )

  app.get(
    '/print/:objectClass/:objectId',
    wrapRequest(async (req, res, wsIds, wsLoginInfo) => {
      const ctx = req.ctx
      const objectId = req.params.objectId
      const objectClass = req.params.objectClass

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Open the DOCX locally to verify it isn't corrupt or password-protected.
  2. Re-upload the file (re-upload fixes truncated uploads) and retry conversion.
  3. Re-save/export the document from Word/LibreOffice to normalize the OOXML, then re-upload.
  4. Check the print service logs for the converter's underlying exception to identify the unsupported feature.
Defensive patterns

Strategy: fallback

Validate before calling

// Sanity-check the DOCX before asking the service to convert
async function looksLikeDocx (file: File): Promise<boolean> {
  const head = new Uint8Array(await file.slice(0, 2).arrayBuffer())
  return head[0] === 0x50 && head[1] === 0x4b // ZIP magic 'PK' — DOCX is a zip container
}

Try / catch

try {
  const res = await fetch(`/convert/${encodeURIComponent(fileKey)}`, { headers })
  if (!res.ok) {
    const body = await res.json()
    if (body.code === 400 && /Failed to convert/.test(body.message)) {
      // surface a user-facing 'document could not be converted, try re-saving it' message
      throw new ConvertError(body.message)
    }
    throw new Error(body.message)
  }
  return await res.json()
} catch (err) { /* handle: prompt user to re-export the DOCX */ }

Prevention

When it happens

Trigger: GET /convert/:file where the stored DOCX is corrupt, truncated, password-protected, uses unsupported Word features, or the uploaded bytes are not actually DOCX despite the stored content type.

Common situations: Files corrupted by interrupted uploads; password-protected documents; files renamed to .docx but really another format; mammoth-style converters choking on exotic OOXML features.

Related errors


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