{"record":{"id":"a42e5072d0a60727","repo":"hcengineering/platform","slug":"failed-to-delete-file-a42e50","errorCode":null,"errorMessage":"Failed to delete file","messagePattern":"Failed to delete file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"foundations/core/packages/storage-client/src/client/front.ts","lineNumber":58,"sourceCode":"    return getPathname(url)\n  }\n\n  async getFileMeta (token: string, workspace: string, file: string): Promise<Record<string, any>> {\n    return {}\n  }\n\n  async deleteFile (token: string, workspace: string, file: string): Promise<void> {\n    const url = this.getFileUrl(workspace, file)\n\n    const response = await fetch(url, {\n      method: 'DELETE',\n      headers: {\n        Authorization: `Bearer ${token}`\n      }\n    })\n\n    if (!response.ok) {\n      throw new Error('Failed to delete file')\n    }\n  }\n\n  async uploadFile (\n    token: string,\n    workspace: string,\n    uuid: string,\n    file: File,\n    options?: FileStorageUploadOptions\n  ): Promise<void> {\n    const formData = new FormData()\n    formData.append('file', file, uuid)\n\n    await uploadXhr(\n      {\n        url: concatLink(this.baseUrl, `/${workspace}`),\n        method: 'POST',\n        headers: { Authorization: `Bearer ${token}` },","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/core/packages/storage-client/src/client/front.ts#L40-L76","documentation":"The front-style storage client's deleteFile sends DELETE <baseUrl>/blob/<workspace>/<file> with a Bearer token and throws this generic Error whenever response.ok is false. As with the other storage clients, the status code and response body are dropped, so the message is intentionally opaque.","triggerScenarios":"deleteFile(token, workspace, file) gets 401 (expired Bearer token), 403 (no permission on workspace), 404 (file UUID or workspace wrong), or 5xx from the storage service.","commonSituations":"Session expired while a bulk cleanup job was running; deleting attachments of an object that was already removed; front storage service scaled down or its ingress misrouting /blob paths; baseUrl pointing to the frontend instead of the storage service.","solutions":["Capture response.status at the throw site (or via a proxy of the client) to identify the failure class.","Refresh the authorization token and retry the delete once.","Validate the file UUID exists via the metadata API before deleting to avoid 404 noise.","Check the storage service health and that the configured baseUrl routes to it."],"exampleFix":"// before\nawait storage.deleteFile(staleToken, workspace, uuid) // throws 'Failed to delete file' on 401\n\n// after\nconst fresh = await renewToken()\nawait storage.deleteFile(fresh, workspace, uuid)","handlingStrategy":"try-catch","validationCode":"// guard inputs before calling deleteFile\nif (token === undefined || token.length === 0) throw new Error('Missing storage token')\nif (workspace === undefined || file === undefined) throw new Error('workspace and file uuid are required')","typeGuard":"null","tryCatchPattern":"try {\n  await storage.deleteFile(token, workspace, file)\n} catch (err) {\n  if (err instanceof Error && err.message === 'Failed to delete file') {\n    // refresh token once and retry; if it fails again, surface to user\n    await storage.deleteFile(await refreshToken(), workspace, file)\n  } else throw err\n}","preventionTips":["Renew the Bearer token proactively before delete-heavy flows.","Confirm baseUrl routes to the storage service, not the frontend app.","Treat 404-class deletes as idempotent success in cleanup jobs.","Check CORS/preflight config for the DELETE method in your ingress."],"tags":["storage","http","network","delete"],"backgroundTag":"storage-delete-request-failed","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}