{"record":{"id":"1050c89dc4465d7f","repo":"n8n-io/n8n","slug":"missing-binary-data-id","errorCode":null,"errorMessage":"Missing binary data ID","messagePattern":"Missing binary data ID","errorType":"exception","errorClass":"BadRequestError","httpStatus":400,"severity":"warning","filePath":"packages/cli/src/controllers/binary-data.controller.ts","lineNumber":52,"sourceCode":"\n\t@Get('/signed', { skipAuth: true })\n\tasync getSigned(_: Request, res: Response, @Query { token }: BinaryDataSignedQueryDto) {\n\t\ttry {\n\t\t\tconst binaryDataId = this.binaryDataService.validateSignedToken(token);\n\t\t\tthis.validateBinaryDataId(binaryDataId);\n\t\t\tawait this.setContentHeaders(binaryDataId, 'download', res);\n\t\t\treturn await this.binaryDataService.getAsStream(binaryDataId);\n\t\t} catch (error) {\n\t\t\tif (error instanceof FileNotFoundError) return res.status(404).end();\n\t\t\tif (error instanceof BadRequestError || error instanceof JsonWebTokenError)\n\t\t\t\treturn res.status(400).end(error.message);\n\t\t\telse throw error;\n\t\t}\n\t}\n\n\tprivate validateBinaryDataId(binaryDataId: string) {\n\t\tif (!binaryDataId) {\n\t\t\tthrow new BadRequestError('Missing binary data ID');\n\t\t}\n\n\t\tconst separatorIndex = binaryDataId.indexOf(':');\n\n\t\tif (separatorIndex === -1) {\n\t\t\tthrow new BadRequestError('Malformed binary data ID');\n\t\t}\n\n\t\tconst mode = binaryDataId.substring(0, separatorIndex);\n\n\t\tif (!isValidNonDefaultMode(mode)) {\n\t\t\tthrow new BadRequestError('Invalid binary data mode');\n\t\t}\n\n\t\tconst path = binaryDataId.substring(separatorIndex + 1);\n\n\t\tif (path === '' || path === '/' || path === '//') {\n\t\t\tthrow new BadRequestError('Malformed binary data ID');","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/cli/src/controllers/binary-data.controller.ts#L34-L70","documentation":"BadRequestError (HTTP 400) 'Missing binary data ID' thrown at binary-data.controller.ts:52 inside `validateBinaryDataId` when the `id` query param is falsy (empty/undefined). The route requires an `id` of shape `<mode>:<path>` before any storage lookup.","triggerScenarios":"Calling `GET /binary-data` or `GET /binary-data/signed`-derived flow without an `id`, with `id=`, or where the DTO coerced it to undefined.","commonSituations":"External/MCP clients omitting `id`; frontend bugs dropping the param; misconfigured reverse-proxy stripping query strings.","solutions":["Always include `?id=<mode>:<path>` in the request.","Validate at the call site before issuing the request — see validationCode.","Log the full request URL on 400 to catch clients that drop the param."],"exampleFix":"// before\nGET /binary-data?action=download\n// 400 Missing binary data ID\n\n// after\nGET /binary-data?id=filesystem:exec-1/file.bin&action=download","handlingStrategy":"validation","validationCode":"function requireBinaryId(id: unknown): asserts id is string {\n  if (typeof id !== 'string' || id.length === 0) throw new TypeError('Missing binary data ID');\n}\n// call before building the request URL","typeGuard":"const hasBinaryId = (q: unknown): q is { id: string } =>\n  typeof q === 'object' && q !== null && typeof (q as any).id === 'string' && (q as any).id.length > 0;","tryCatchPattern":"try { await get(req); } catch (e) { if (e instanceof BadRequestError && /Missing/.test(e.message)) {/* ask caller for id */} }","preventionTips":["Always include `?id=<mode>:<path>` when calling the binary-data route.","Log full request URLs on 400 to find clients that drop query params.","Use a typed query DTO and fail at the edge when `id` is missing."],"tags":["binary-data","rest","bad-request","validation"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}