{"record":{"id":"6baf86e6a3365231","repo":"hcengineering/platform","slug":"missing-blob-name","errorCode":null,"errorMessage":"Missing blob name","messagePattern":"Missing blob name","errorType":"http","errorClass":"HttpError","httpStatus":400,"severity":"error","filePath":"pods/preview/src/middleware.ts","lineNumber":83,"sourceCode":"    next(err)\n  }\n}\n\n/**\n * Validates blob route params and ensures the caller's token grants access to\n * the workspace taken from the URL. Must run after `withAuthorization`, which\n * guarantees a token is present.\n */\nexport const withBlob = (req: RequestWithAuth, res: Response, next: NextFunction): void => {\n  try {\n    const workspace = req.params.workspace\n    const name = req.params.name\n\n    if (workspace === undefined || workspace === '') {\n      throw new HttpError(400, 'Missing workspace')\n    }\n    if (name === undefined || name === '') {\n      throw new HttpError(400, 'Missing blob name')\n    }\n\n    const token = req.token\n    if (token == null) {\n      throw new HttpError(401, 'Unauthorized')\n    }\n\n    const hasWorkspaceAccess =\n      (token.workspace as string) === workspace || token.account === systemAccountUuid || token.extra?.admin === 'true'\n    if (!hasWorkspaceAccess) {\n      throw new HttpError(401, 'Unauthorized')\n    }\n\n    next()\n  } catch (err: any) {\n    next(err)\n  }\n}","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/pods/preview/src/middleware.ts#L65-L101","documentation":"withBlob validates req.params.name and throws HttpError 400 'Missing blob name' when the name param is undefined or empty. This runs after the workspace check in the same middleware.","triggerScenarios":"Blob endpoint request where the :name route parameter is absent or empty — e.g. URL ends at /blob/{workspace}/ with no blob name.","commonSituations":"Trailing-slash URL missing the filename; client variable holding the blob name is null/undefined at request time; route pattern mismatch so name isn't captured.","solutions":["Append the blob name to the request URL (/blob/{workspace}/{name})","Ensure the blob name variable is set before issuing the request","Verify the express route defines :name so req.params.name is populated","Encode the blob name (encodeURIComponent) so special characters don't break the path"],"exampleFix":"// before\nfetch(`/blob/${workspace}/${name}`)\n// after\nif (!name) throw new Error('blob name is required')\nfetch(`/blob/${encodeURIComponent(workspace)}/${encodeURIComponent(name)}`)","handlingStrategy":"validation","validationCode":"if (!isNonEmptyString(name)) {\n  throw new HttpError(400, 'blob name is required')\n}\nconst url = `/blob/${encodeURIComponent(workspace)}/${encodeURIComponent(name)}`","typeGuard":"function isNonEmptyString (v: unknown): v is string {\n  return typeof v === 'string' && v.trim().length > 0\n}","tryCatchPattern":"try {\n  const res = await fetch(url)\n  if (res.status === 400) {\n    console.error('Check blob request params: workspace and name must be non-empty')\n  }\n} catch (err) { /* handle */ }","preventionTips":["Always pass the blob name explicitly; never rely on defaults in fetch wrappers","Encode blob names to survive slashes/special characters","Add a client-side guard that the name variable is set before request","Keep server route and client URL templates in sync"],"tags":["http","validation","params"],"backgroundTag":"missing-required-parameter","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}