{"record":{"id":"3e82611c890015f6","repo":"hcengineering/platform","slug":"missing-filename","errorCode":null,"errorMessage":"missing filename","messagePattern":"missing filename","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"services/datalake/pod-datalake/src/handlers/s3.ts","lineNumber":43,"sourceCode":"  res: Response,\n  datalake: Datalake\n): Promise<void> {\n  const workspace = req.params.workspace as WorkspaceUuid\n  const { location, bucket } = await datalake.selectStorage(ctx, workspace)\n  res.status(200).json({ location, bucket: bucket.bucket })\n}\n\nexport async function handleS3CreateBlob (\n  ctx: MeasureContext,\n  req: Request,\n  res: Response,\n  datalake: Datalake\n): Promise<void> {\n  const { name } = req.params\n  const workspace = req.params.workspace as WorkspaceUuid\n  const filename = req.body.filename as string\n  if (filename == null) {\n    res.status(400).send('missing filename')\n    return\n  }\n\n  try {\n    await datalake.create(ctx, workspace, name, filename)\n    res.status(200).send()\n  } catch (err: any) {\n    Analytics.handleError(err)\n    const error = err instanceof Error ? err.message : String(err)\n    ctx.error('failed to create blob', { workspace, name, error })\n    res.status(500).send()\n  }\n}\n","sourceCodeStart":25,"sourceCodeEnd":57,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/services/datalake/pod-datalake/src/handlers/s3.ts#L25-L57","documentation":"handleS3CreateBlob (S3-compatible API) requires req.body.filename to create a blob. When filename is null/undefined the handler responds 400 'missing filename'. The filename is used as the object key/metadata via datalake.create.","triggerScenarios":"POSTing to the S3 create-blob route without a filename field in the JSON body, sending filename: null, or sending a non-JSON body so body parsing yields no filename.","commonSituations":"S3 clients/tools that don't send this custom extension field; forgetting Content-Type: application/json; scripts copied from the plain upload endpoint that pass the name only as a path param.","solutions":["Include \"filename\" in the JSON body of the create request.","Set Content-Type: application/json so the body parser populates req.body.","If migrating from the plain upload API, map the path name into the filename field for this S3 endpoint."],"exampleFix":"// before\ncurl -X POST $URL -d '{}'\n// after\ncurl -X POST $URL -H 'Content-Type: application/json' -d '{\"filename\":\"report.pdf\"}'","handlingStrategy":"validation","validationCode":"if (!filename) {\n  throw new Error('filename is required to create an S3 blob')\n}","typeGuard":"function hasFilename(b: unknown): b is { filename: string } {\n  return !!b && typeof (b as any).filename === 'string' && (b as any).filename.length > 0\n}","tryCatchPattern":"const res = await fetch(url, { method: 'POST', headers: json, body: JSON.stringify({ filename }) })\nif (res.status === 400 && (await res.text()) === 'missing filename') {\n  throw new Error('include filename in the request body')\n}","preventionTips":["Build the create-blob body from a typed interface including filename.","Always send application/json for this endpoint.","Validate filename non-empty before calling the S3 create route."],"tags":["http","s3","validation","bad-request"],"backgroundTag":"missing-request-body-field","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}