hcengineering/platform · error

err.message?.length > 0 ? err.message : 'Internal Server Err

Error message

err.message?.length > 0 ? err.message : 'Internal Server Error'

What it means

This is the datalake Express global error-handling middleware. When any route handler throws or calls next(err) and the error is not an ApiError, it logs the error, reports it to Analytics (unless the message is a known client-abort case like 'Premature close' or 'File too large'), and responds 500 with err.message, or the literal 'Internal Server Error' when the message is empty or undefined. It exists as the last-resort handler so unhandled server errors always produce a JSON response instead of a hung request.

Source

Thrown at services/datalake/pod-datalake/src/server.ts:324

      'File too large' // happens when the file exceeds the limit set by express-fileupload
    ]

    return !ignoreMessages.includes(err.message)
  }

  app.use((err: any, _req: any, res: any, _next: any) => {
    ctx.error(err.message, { code: err.code, message: err.message })
    if (err instanceof ApiError) {
      res.status(err.code).send({ code: err.code, message: err.message })
      return
    }

    // do not send some errors to analytics
    if (sendErrorToAnalytics(err)) {
      Analytics.handleError(err)
    }

    res.status(500).json({ message: err.message?.length > 0 ? err.message : 'Internal Server Error' })
  })

  app.get('/api/v1/statistics', (req, res) => {
    try {
      const token = req.query.token as string
      const payload = decodeToken(token)
      const admin = payload.extra?.admin === 'true'
      res.setHeader('Content-Type', 'application/json')
      res.setHeader('Connection', 'keep-alive')
      res.setHeader('Keep-Alive', 'timeout=5')
      res.setHeader('Cache-Control', cacheControlNoCache)

      const json = JSON.stringify({
        metrics: metricsAggregate((ctx as any).metrics),
        statistics: {
          cpu: getCPUInfo(),
          memory: getMemoryInfo()
        },

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Check the server logs at the same timestamp (ctx.error with code/message) to find the root-cause error thrown by the failing route.
  2. If the message is 'Premature close' / 'Unexpected end of form' / 'File too large', fix the client: complete or restart the upload, or raise the express-fileupload size limit.
  3. If it is a storage or network failure, verify object-storage connectivity and credentials, then retry the request.
  4. If the message is 'Internal Server Error', inspect Analytics entries for the underlying error object, since no useful message reached the response.

Example fix

// before (client ignores aborts and gets opaque 500s)
await fetch(uploadUrl, { method: 'PUT', body: stream, signal: undefined })
// after (client handles aborts explicitly)
const ctrl = new AbortController()
try {
  await fetch(uploadUrl, { method: 'PUT', body: stream, signal: ctrl.signal })
} catch (e) {
  if (ctrl.signal.aborted) console.warn('upload cancelled')
  else throw e
}
Defensive patterns

Strategy: try-catch

Validate before calling

// client: ensure upload stream is complete and within size limits before sending
if (fileSize > MAX_UPLOAD_SIZE) throw new Error('File exceeds server upload limit')
if (stream.destroyed || stream.readableEnded) throw new Error('Upload stream already closed')

Type guard

function isApiError(e: unknown): e is { code: number; message: string } {
  return typeof e === 'object' && e !== null && 'code' in e && typeof (e as any).code === 'number'
}

Try / catch

try {
  const res = await fetch(datalakeUrl, opts)
  if (!res.ok) {
    const body = await res.json().catch(() => ({}))
    if (res.status === 500 && body.message === 'Internal Server Error') throw new Error('datalake 500: check server logs')
    throw new Error(body.message ?? `datalake ${res.status}`)
  }
} catch (e) {
  // retry idempotent reads; surface message; treat aborts ('Premature close') as client-cancelled
}

Prevention

When it happens

Trigger: Any datalake HTTP request (uploads, workspace/object routes, statistics) whose handler throws a non-ApiError: malformed multipart bodies, storage adapter failures, unexpected exceptions in route logic, or body-parsing errors forwarded via next(err).

Common situations: S3/blob storage outages mid-upload, express-fileupload limits ('File too large'), clients aborting uploads ('Unexpected end of form', 'Premature close'), or bugs in a handler throwing undefined-message errors.

Understand the failure class

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/adba73a2fa140114. Report an issue: GitHub.