n8n-io/n8n · warning
error.message
Error message
error.message
What it means
HTTP 400 with `error.message` body returned at binary-data.controller.ts:30 when `GET /binary-data` throws a `BadRequestError` from `validateBinaryDataId` or `setContentHeaders`. The literal message ('Missing binary data ID', 'Malformed binary data ID', 'Invalid binary data mode', or 'Content not viewable') is sent verbatim via `res.status(400).end(error.message)`.
Source
Thrown at packages/cli/src/controllers/binary-data.controller.ts:30
import { BadRequestError } from '@/errors/response-errors/bad-request.error';
@RestController('/binary-data')
export class BinaryDataController {
constructor(private readonly binaryDataService: BinaryDataService) {}
@Get('/')
async get(
_: Request,
res: Response,
@Query { id: binaryDataId, action, fileName, mimeType }: BinaryDataQueryDto,
) {
try {
this.validateBinaryDataId(binaryDataId);
await this.setContentHeaders(binaryDataId, action, res, fileName, mimeType);
return await this.binaryDataService.getAsStream(binaryDataId);
} catch (error) {
if (error instanceof FileNotFoundError) return res.status(404).end();
if (error instanceof BadRequestError) return res.status(400).end(error.message);
else throw error;
}
}
@Get('/signed', { skipAuth: true })
async getSigned(_: Request, res: Response, @Query { token }: BinaryDataSignedQueryDto) {
try {
const binaryDataId = this.binaryDataService.validateSignedToken(token);
this.validateBinaryDataId(binaryDataId);
await this.setContentHeaders(binaryDataId, 'download', res);
return await this.binaryDataService.getAsStream(binaryDataId);
} catch (error) {
if (error instanceof FileNotFoundError) return res.status(404).end();
if (error instanceof BadRequestError || error instanceof JsonWebTokenError)
return res.status(400).end(error.message);
else throw error;
}
}View on GitHub (pinned to 5ac6606e81)
Solutions
- Send a well-formed `id` of shape `<mode>:<path>` where `<mode>` ∈ {filesystem, filesystem-v2, s3, azure, database}.
- For `action=view`, supply a MIME type in `ViewableMimeTypes` (json, common image/audio/video, text/* excluding html/svg).
- When the frontend constructs the URL, derive `id` from the execution's `binary` data rather than hand-assembling it.
- If storage mode was changed, re-run the execution so binary IDs use the new mode prefix.
Example fix
// before GET /binary-data?id=abc&action=view // 400 Malformed binary data ID // after GET /binary-data?id=filesystem:exec-123/data.json&action=download
Defensive patterns
Strategy: validation
Validate before calling
const STORED_MODES = ['filesystem','filesystem-v2','s3','azure','database'] as const;
function validBinaryId(id: string) {
const i = id.indexOf(':');
if (i === -1) return false;
const mode = id.slice(0, i);
const path = id.slice(i + 1);
return STORED_MODES.includes(mode as any) && path !== '' && path !== '/' && path !== '//';
}
// guard the fetch: if (!validBinaryId(id)) throw new TypeError('bad id') Type guard
const isStoredMode = (m: string): m is typeof STORED_MODES[number] =>
['filesystem','filesystem-v2','s3','azure','database'].includes(m);
const isValidBinaryId = (id: unknown): id is string =>
typeof id === 'string' && id.includes(':') &&
isStoredMode(id.slice(0, id.indexOf(':'))) &&
!['','/','//'].includes(id.slice(id.indexOf(':') + 1)); Try / catch
try {
await binaryController.get(...);
} catch (e) {
if (e instanceof BadRequestError) {
// surface e.message to the user; do not retry the same id
}
} Prevention
- Always derive binary IDs from execution response payloads, never construct by hand.
- After changing N8N_DEFAULT_BINARY_DATA_MODE, re-run executions so IDs use the new mode prefix.
- Frontend should validate the id format before navigating to the binary URL.
When it happens
Trigger: Calling `GET /binary-data?id=&action=view`, omitting `id`, using an `id` without a `:` separator, with an unknown storage mode prefix, or requesting `action=view` on a non-viewable MIME type. The frontend binary viewer typically hits this on malformed payloads.
Common situations: Manual/incorrect binary URL construction; MCP/external clients that build the `id` by hand; switching `N8N_DEFAULT_BINARY_DATA_MODE` so old `default:` IDs become invalid; viewing an unsupported MIME type.
Related errors
- Missing binary data ID
- Malformed binary data ID
- Invalid binary data mode
- Content not viewable
- output.error.errors[0]
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/997b0ca7e0e63541.
Report an issue: GitHub.