{"record":{"id":"ccde4db8e1e11b73","repo":"hcengineering/platform","slug":"internal-server-error-ccde4d","errorCode":null,"errorMessage":"Internal Server Error","messagePattern":"Internal Server Error","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"services/backup/backup-api-pod/src/server.ts","lineNumber":359,"sourceCode":"          return\n        }\n      }\n\n      // Forward the R2 object with original headers\n      // return new Response(fileInfo.body, {\n      //   headers: responseHeaders\n      // })\n      res.status(200).set(responseHeaders)\n      ;(await storage.load(file)).pipe(res)\n      return\n    }\n    res.status(404).end('Not found')\n  }\n\n  app.get('/api/backup/:workspace/:file(*)', (req, res) => {\n    void handleBackup(req, res).catch((err) => {\n      console.error('request error', err)\n      res.status(500).end('Internal Server Error')\n    })\n  })\n\n  app.get('/', (req, res) => {\n    res.send(`Huly&reg; Backup&trade; <a href=\"https://huly.io\">https://huly.io</a>\n      &copy; 2024 <a href=\"https://hulylabs.com\">Huly Labs</a>`)\n  })\n\n  const sendErrorToAnalytics = (err: any): boolean => {\n    const ignoreMessages = [\n      'Unexpected end of form', // happens when the client closes the connection before the upload is complete\n      'Premature close', // happens when the client closes the connection before the upload is complete\n      'File too large' // happens when the file exceeds the limit set by express-fileupload\n    ]\n\n    return !ignoreMessages.includes(err.message)\n  }\n","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/backup/backup-api-pod/src/server.ts#L341-L377","documentation":"The route wrapper around handleBackup catches any unhandled promise rejection and responds HTTP 500 'Internal Server Error'. It fires when code after authentication/authorization fails — e.g. createStorageBackupStorage throwing, storage.statInfo/load raising, gunzip failing on corrupt backup.json.gz, or the storage stream erroring mid-pipe.","triggerScenarios":"Storage adapter misconfiguration (bad bucket config from env), corrupt gzip metadata files, storage backend outages, or any exception thrown outside the inner try/catch blocks of handleBackup.","commonSituations":"Huly operators see this when object-storage credentials/config are wrong (storageConfigFromEnv failing), during storage-backend incidents, or when a backup.json.gz in the bucket is truncated/corrupt.","solutions":["Check the backup pod logs for the 'request error' entry to identify the underlying exception","Validate storage env config (bucket/credentials) used by storageConfigFromEnv","Inspect/repair the workspace's backup.json.gz if gunzip errors appear in logs","Retry after confirming the object-storage backend is healthy"],"exampleFix":"// client-side\n// before\nconst res = await fetch(url)\nconst body = await res.text()\n// after\nconst res = await fetch(url)\nif (res.status === 500) throw new Error('backup API internal error, check server logs')\nconst body = await res.text()","handlingStrategy":"try-catch","validationCode":"// verify storage config before starting downloads\nconst cfg = storageConfigFromEnv(config.Storage)\nif (!cfg.storages?.length) throw new Error('No storage configured')","typeGuard":"function isStorageError(err: unknown): boolean {\n  return typeof err === 'object' && err !== null && /storage|gunzip|ECONN|bucket/i.test((err as any).message ?? '')\n}","tryCatchPattern":"const res = await fetch(url, { headers })\nif (res.status === 500) {\n  const body = await res.text()\n  throw new Error(`Backup API failed (500). Inspect server 'request error' logs: ${body}`)\n}","preventionTips":["Validate storage env config at service startup","Alert on object-storage backend health","Watch logs for gunzip errors indicating corrupt backup.json.gz","Retry downloads after transient storage incidents"],"tags":["http-500","internal-server-error","storage"],"backgroundTag":"internal-server-error","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}