{"record":{"id":"a42333fa1b3d3b68","repo":"hcengineering/platform","slug":"file-file-not-found","errorCode":null,"errorMessage":"File ${file} not found","messagePattern":"File (.+?) not found","errorType":"http","errorClass":"ApiError","httpStatus":404,"severity":"error","filePath":"services/print/pod-print/src/server.ts","lineNumber":251,"sourceCode":"      const printId = `print-${generateId()}`\n\n      await storageAdapter.put(ctx, wsIds, printId, printRes, `application/${options.kind}`, printRes.length)\n\n      res.contentType('application/json')\n      res.send({ id: printId })\n    })\n  )\n\n  app.get(\n    '/convert/:file',\n    wrapRequest(async (req, res, wsUuid) => {\n      const convertableFormats = ['application/vnd.openxmlformats-officedocument.wordprocessingml.document']\n      const ctx = req.ctx\n      const file = req.params.file\n      const stat = await storageAdapter.stat(ctx, wsUuid, file)\n\n      if (stat === undefined) {\n        throw new ApiError(404, `File ${file} not found`)\n      }\n\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","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/print/pod-print/src/server.ts#L233-L269","documentation":"The /convert/:file endpoint first checks that the requested file exists in the workspace's storage via storageAdapter.stat. If no object with that name exists, the endpoint throws this 404 ApiError. Conversion never runs on missing files.","triggerScenarios":"GET /convert/:file where the file key doesn't exist in the workspace storage — wrong file name/UUID, file uploaded to a different workspace, or file already deleted/purged from the storage adapter.","commonSituations":"Client caching file names after the document was deleted; using a display filename instead of the storage key; cross-workspace token used against another workspace's files; typos in the path parameter.","solutions":["Verify the file identifier is the exact storage key used at upload time (from storageAdapter.put / upload response).","Confirm the request token resolves to the same workspace the file was uploaded to.","Re-upload the file if it was deleted, then convert.","List/stat the object first to confirm existence before calling convert."],"exampleFix":"// before\nawait fetch(`/convert/${displayName}.docx`, { headers })\n// after\nconst stat = await fetch(`${storageUrl}/${fileKey}`, { method: 'HEAD', headers })\nif (stat.ok) await fetch(`/convert/${encodeURIComponent(fileKey)}`, { headers })","handlingStrategy":"validation","validationCode":"async function assertFileExists (fileKey: string, headers: HeadersInit): Promise<void> {\n  const res = await fetch(`/convert/${encodeURIComponent(fileKey)}`, { method: 'HEAD', headers })\n  // Endpoint itself 404s; verify via your own upload registry instead:\n  if (!uploadedKeys.has(fileKey)) throw new Error(`File key not uploaded to this workspace: ${fileKey}`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(`/convert/${encodeURIComponent(fileKey)}`, { headers })\n  if (res.status === 404) {\n    const body = await res.json()\n    throw new Error(`File missing in workspace storage: ${body.message}`)\n  }\n  return await res.json()\n} catch (err) { /* handle: re-upload or surface to user */ }","preventionTips":["Keep a client-side record of storage keys returned at upload time and use those exact keys.","Encode the file key in the path; avoid using display names as keys.","Handle workspace tokens carefully — files live per workspace.","Treat deleted files as terminal: don't retry 404s, prompt re-upload."],"tags":["http-404","storage","file-not-found","convert"],"backgroundTag":"file-not-found","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}