hcengineering/platform · error
Internal Server Error
Error message
Internal Server Error
What it means
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.
Source
Thrown at services/backup/backup-api-pod/src/server.ts:359
return
}
}
// Forward the R2 object with original headers
// return new Response(fileInfo.body, {
// headers: responseHeaders
// })
res.status(200).set(responseHeaders)
;(await storage.load(file)).pipe(res)
return
}
res.status(404).end('Not found')
}
app.get('/api/backup/:workspace/:file(*)', (req, res) => {
void handleBackup(req, res).catch((err) => {
console.error('request error', err)
res.status(500).end('Internal Server Error')
})
})
app.get('/', (req, res) => {
res.send(`Huly® Backup™ <a href="https://huly.io">https://huly.io</a>
© 2024 <a href="https://hulylabs.com">Huly Labs</a>`)
})
const sendErrorToAnalytics = (err: any): boolean => {
const ignoreMessages = [
'Unexpected end of form', // happens when the client closes the connection before the upload is complete
'Premature close', // happens when the client closes the connection before the upload is complete
'File too large' // happens when the file exceeds the limit set by express-fileupload
]
return !ignoreMessages.includes(err.message)
}
View on GitHub (pinned to 63e28dc964)
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
Example fix
// client-side
// before
const res = await fetch(url)
const body = await res.text()
// after
const res = await fetch(url)
if (res.status === 500) throw new Error('backup API internal error, check server logs')
const body = await res.text() Defensive patterns
Strategy: try-catch
Validate before calling
// verify storage config before starting downloads
const cfg = storageConfigFromEnv(config.Storage)
if (!cfg.storages?.length) throw new Error('No storage configured') Type guard
function isStorageError(err: unknown): boolean {
return typeof err === 'object' && err !== null && /storage|gunzip|ECONN|bucket/i.test((err as any).message ?? '')
} Try / catch
const res = await fetch(url, { headers })
if (res.status === 500) {
const body = await res.text()
throw new Error(`Backup API failed (500). Inspect server 'request error' logs: ${body}`)
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
Related errors
- get-file-error
- Cannot create message, group not found: cardId = ${event.car
- Missing response body
- Network error ${error}
- await response.text()
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/ccde4db8e1e11b73.
Report an issue: GitHub.