{"record":{"id":"95b42a7e880f1e7f","repo":"hcengineering/platform","slug":"missing-response-body-95b42a","errorCode":null,"errorMessage":"Missing response body","messagePattern":"Missing response body","errorType":"exception","errorClass":"DatalakeError","httpStatus":null,"severity":"error","filePath":"foundations/server/packages/datalake/src/client.ts","lineNumber":140,"sourceCode":"    return (await response.json()) as ListObjectOutput\n  }\n\n  async getObject (ctx: MeasureContext, workspace: WorkspaceUuid, objectName: string): Promise<Readable | undefined> {\n    const url = this.getObjectUrl(ctx, workspace, objectName)\n\n    let response\n    try {\n      response = await fetchSafe(ctx, url, { headers: { ...this.headers } })\n    } catch (err: any) {\n      if (err.name === 'NotFoundError') {\n        return undefined\n      }\n      throw err\n    }\n\n    if (response.body == null) {\n      ctx.error('bad datalake response', { objectName })\n      throw new DatalakeError('Missing response body')\n    }\n\n    return Readable.fromWeb(response.body as any)\n  }\n\n  async getPartialObject (\n    ctx: MeasureContext,\n    workspace: WorkspaceUuid,\n    objectName: string,\n    offset: number,\n    length?: number\n  ): Promise<Readable | undefined> {\n    const url = this.getObjectUrl(ctx, workspace, objectName)\n    const headers = {\n      ...this.headers,\n      Range: length !== undefined ? `bytes=${offset}-${offset + length - 1}` : `bytes=${offset}`\n    }\n","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/foundations/server/packages/datalake/src/client.ts#L122-L158","documentation":"getObject fetches a blob from the datalake service and returns it as a readable stream. If the HTTP response succeeds but has a null body, the client logs 'bad datalake response' and throws DatalakeError('Missing response body').","triggerScenarios":"GET object succeeds at HTTP level but the proxy/gateway strips the body, or the server returns an empty/204-style response for an existing objectName.","commonSituations":"Reverse proxy misconfiguration swallowing bodies; datalake service returning empty responses under error conditions not mapped to HTTP status; requesting an object whose content was truncated/lost server-side.","solutions":["Verify the object exists via statObject before/after the failure","Check proxy/gateway config (nginx buffering, minio/datalake endpoint) so bodies pass through","Retry the request; inspect datalake server logs for the objectName"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const stat = await client.statObject(ctx, workspace, objectName)\nif (stat == null) throw new Error(`object ${objectName} does not exist`)\nif (stat.size === 0) console.warn(`object ${objectName} is empty; body may be null`)","typeGuard":null,"tryCatchPattern":"try {\n  const stream = await client.getObject(ctx, workspace, objectName)\n} catch (err) {\n  if (err instanceof DatalakeError && err.message === 'Missing response body') {\n    // retry once, then fail with a clear message\n  } else throw err\n}","preventionTips":["statObject before large/critical reads","Check proxy/gateway configs that may strip response bodies","Monitor datalake server health; alert on repeated empty responses"],"tags":["network","datalake","response"],"backgroundTag":"empty-response-body","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}