{"record":{"id":"4b99576e3e8716b8","repo":"hcengineering/platform","slug":"failed-to-convert","errorCode":null,"errorMessage":"Failed to convert","messagePattern":"Failed to convert","errorType":"http","errorClass":"ApiError","httpStatus":400,"severity":"error","filePath":"services/print/pod-print/src/server.ts","lineNumber":271,"sourceCode":"\n      if (!convertableFormats.includes(stat.contentType)) {\n        throw new ApiError(400, `File of this type (${stat.contentType}) cannot be converted`)\n      }\n\n      const convertId = getConvertId(file, stat.etag)\n      const convertStats = await storageAdapter.stat(ctx, wsUuid, convertId)\n\n      if (convertStats === undefined) {\n        const originalFile = await storageAdapter.read(ctx, wsUuid, file)\n\n        if (originalFile === undefined) {\n          throw new ApiError(404, `File ${file} not found`)\n        }\n\n        const htmlRes = await ctx.with('convertToHtml', {}, () => convertToHtml(Buffer.concat(originalFile as any)))\n\n        if (htmlRes === undefined) {\n          throw new ApiError(400, 'Failed to convert')\n        }\n\n        const htmlBuf = Buffer.from(htmlRes)\n\n        await storageAdapter.put(ctx, wsUuid, convertId, htmlBuf, 'text/html', htmlBuf.length)\n      }\n\n      res.contentType('application/json')\n      res.send({ id: convertId })\n    })\n  )\n\n  app.get(\n    '/print/:objectClass/:objectId',\n    wrapRequest(async (req, res, wsIds, wsLoginInfo) => {\n      const ctx = req.ctx\n      const objectId = req.params.objectId\n      const objectClass = req.params.objectClass","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/print/pod-print/src/server.ts#L253-L289","documentation":"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.","triggerScenarios":"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.","commonSituations":"Files corrupted by interrupted uploads; password-protected documents; files renamed to .docx but really another format; mammoth-style converters choking on exotic OOXML features.","solutions":["Open the DOCX locally to verify it isn't corrupt or password-protected.","Re-upload the file (re-upload fixes truncated uploads) and retry conversion.","Re-save/export the document from Word/LibreOffice to normalize the OOXML, then re-upload.","Check the print service logs for the converter's underlying exception to identify the unsupported feature."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"// Sanity-check the DOCX before asking the service to convert\nasync function looksLikeDocx (file: File): Promise<boolean> {\n  const head = new Uint8Array(await file.slice(0, 2).arrayBuffer())\n  return head[0] === 0x50 && head[1] === 0x4b // ZIP magic 'PK' — DOCX is a zip container\n}","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(`/convert/${encodeURIComponent(fileKey)}`, { headers })\n  if (!res.ok) {\n    const body = await res.json()\n    if (body.code === 400 && /Failed to convert/.test(body.message)) {\n      // surface a user-facing 'document could not be converted, try re-saving it' message\n      throw new ConvertError(body.message)\n    }\n    throw new Error(body.message)\n  }\n  return await res.json()\n} catch (err) { /* handle: prompt user to re-export the DOCX */ }","preventionTips":["Validate uploads: check the ZIP magic bytes and that the docx opens in a parser before storing.","Reject password-protected documents at upload time.","Ask users to re-save/export from Word or LibreOffice if conversion fails.","Check print-service converter logs for the exact parse failure to guide users."],"tags":["http-400","docx","conversion","file-format"],"backgroundTag":"conversion-failed","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}