{"record":{"id":"2363324799bd11ac","repo":"hcengineering/platform","slug":"not-found","errorCode":null,"errorMessage":"Not Found","messagePattern":"Not Found","errorType":"exception","errorClass":"NotFoundError","httpStatus":404,"severity":"error","filePath":"pods/preview/src/service.ts","lineNumber":138,"sourceCode":"\n        return {\n          filePath: thumbPath,\n          mimeType: contentType\n        }\n      })\n    })\n  }\n\n  @withContext('stat-blob')\n  async statBlob (ctx: MeasureContext, workspace: WorkspaceUuid, name: string): Promise<Blob> {\n    const wsId = { uuid: workspace } as any\n\n    const stat = await this.storage.stat(ctx, wsId, name)\n    if (stat !== undefined) {\n      return stat\n    }\n\n    throw new NotFoundError()\n  }\n\n  findProvider (ctx: MeasureContext, contentType: string): PreviewProvider {\n    const provider = this.providers.find((it) => it.supports(contentType))\n    if (provider != null) {\n      return provider\n    }\n\n    throw new BadRequestError(`Unsupported content type: ${contentType}`)\n  }\n\n  private imageKey (workspaceId: string, name: string): string {\n    return `image/${workspaceId}/${name}`\n  }\n\n  private thumbnailKey (workspaceId: string, name: string, params: ThumbnailParams): string {\n    return `thumbnail/${workspaceId}/${name}-${params.width}-${params.height}-${params.format}`\n  }","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/pods/preview/src/service.ts#L120-L156","documentation":"statBlob looks up the blob in the storage adapter (storage.stat). If the storage adapter returns undefined the blob does not exist for the workspace, and the service throws NotFoundError. This is the preview service's canonical 'no such object' response for metadata/thumbnail requests.","triggerScenarios":"Calling the preview metadata or thumbnail endpoint with a workspace/name pair that has no corresponding object in storage — wrong or stale blob name, blob deleted, wrong workspace uuid, or storage backend connectivity returning no object.","commonSituations":"Clients caching blob names after deletion, typos in name/uuid, cross-environment storage (e.g. pointing at a bucket without the uploaded object), race where upload has not completed before preview is requested.","solutions":["Verify the blob name and workspace uuid against the record in your application DB.","Confirm the object exists in the underlying storage (S3/MinIO bucket) under that key.","Ensure upload completed before requesting the preview; retry after the upload finishes.","Check that the preview service is configured against the same storage adapter/workspace as the uploading service."],"exampleFix":"// before\nconst meta = await preview.metadata(ctx, workspace, name)\n// after\nconst stat = await storage.stat(ctx, { uuid: workspace }, name)\nif (stat === undefined) return null // skip preview for missing blob\nconst meta = await preview.metadata(ctx, workspace, name)","handlingStrategy":"validation","validationCode":"const stat = await storage.stat(ctx, { uuid: workspace }, name)\nif (stat === undefined) {\n  return null // blob gone; skip preview request entirely\n}","typeGuard":null,"tryCatchPattern":"try {\n  const meta = await preview.metadata(ctx, workspace, name)\n} catch (err) {\n  if (err.name === 'NotFoundError' || /not found/i.test(err.message)) return null\n  throw err\n}","preventionTips":["Confirm name/workspace before calling; do not reuse names after deletion.","Ensure upload completion precedes preview requests.","Point the preview service at the same storage backend as uploads.","Handle 404 as an expected outcome for deleted blobs."],"tags":["preview","storage","not-found"],"backgroundTag":"blob-not-found","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}