{"record":{"id":"b6c1929ffa33ed41","repo":"Zie619/n8n-workflows","slug":"missing-binary-data","errorCode":null,"errorMessage":"Missing binary data","messagePattern":"Missing binary data","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"workflows/Webhook/0453_Webhook_Code_Create_Webhook.json","lineNumber":861,"sourceCode":"        560,\n        280\n      ],\n      \"parameters\": {\n        \"jsCode\": \"const text = $input.first().json.command_text;\\nconst parts = text.split(' ');\\n\\n\\n// GET COMMAND\\n// for example /cloudbot info mutasem\\n// should return \\\"info\\\"\\nconst command = parts[0];\\n\\n\\n// GET FLAGS \\n// for example /cloudbot info mutasem --test --flag\\n// should return ['--test', '--flag']\\nconst flags = parts.filter((part) => part.startsWith('--'));\\n\\n\\n// GET PARAMS\\n// for example /cloudbot info mutasem test\\n// should return [\\\"mutasem\\\", \\\"test\\\"]\\nlet params = parts\\n  .filter((part, i) => i > 0 && !part.startsWith('--'));\\nparams = params.filter((param, i) => {\\n  if (param === '-e') {\\n    return false;\\n  }\\n  if (params[i - 1] === '-e') {\\n    return false;\\n  }\\n\\n  return true;\\n});\\n\\n\\n// GET ENV VARS\\n// for example /cloudbot info mutasem -e env=prod\\n// should return {env: \\\"prod\\\"}\\nconst env = parts.filter((val, i) => {\\n  return i > 0 && parts[i - 1] === '-e';\\n})\\n  .reduce((accu, opt) => {\\n  if (!opt.includes('=')) {\\n    return accu;\\n  }\\n\\n  const key = opt.split('=')[0];\\n  const val = opt.split('=')[1];\\n  \\n  accu[key] = clean(val);\\n  return accu;\\n}, {});\\n\\n// Add workflow to run\\nconst commands = $input.first().json.commands;\\nlet workflow;\\nif (commands[command]) {\\n  workflow = commands[command];\\n}\\n\\nreturn {\\n  ...$input.first().json,\\n  command,\\n  flags,\\n  env,\\n  params,\\n  workflow,\\n}\\n\\nfunction clean(str) {\\n  return str.replaceAll(`‘`, '\\\\'').replaceAll('“', '\\\"').replaceAll('”', '\\\"').replaceAll('’', '\\\\'');\\n}\"\n      },\n      \"typeVersion\": 1,\n      \"notes\": \"This code node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"22b8502c-dec3-4456-9947-639761517881\",\n      \"name\": \"Validate webhook signature\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"position\": [\n        100,\n        280\n      ],\n      \"parameters\": {\n        \"jsCode\": \"const SIGNING_SECRET = $input.first().json.slack_secret_signature;\\nconst item = $('Webhook to call for Slack command').first();\\n\\nif (!item.binary) {\\n  throw new Error('Missing binary data');\\n}\\n\\nconst crypto = require('crypto');\\nconst { binary: { data } } = item;\\n\\nif (\\n  !item.json.headers['x-slack-request-timestamp'] ||\\n  Math.abs(\\n    Math.floor(new Date().getTime() / 1000) -\\n      +item.json.headers['x-slack-request-timestamp']\\n  ) > 300\\n) {\\n  throw new Error('Unauthorized, request not fresh');\\n}\\n\\nconst rawBody = Buffer.from(data.data, 'base64').toString()\\n\\n// compute the basestring\\nconst baseStr = `v0:${item.json.headers['x-slack-request-timestamp']}:${rawBody}`;\\n\\n// extract the received signature from the request headers\\nconst receivedSignature = item.json.headers['x-slack-signature'];\\n\\nconst expectedSignature = `v0=${crypto.createHmac('sha256', SIGNING_SECRET)\\n.update(baseStr, 'utf8')\\n.digest('hex')}`;\\n\\n// match the two signatures\\nif (expectedSignature !== receivedSignature) {\\nthrow new Error('Unauthorized, umatched signatures');\\n}\\n\\nreturn $input.all();\"\n      },\n      \"typeVersion\": 2,\n      \"notes\": \"This code node performs automated tasks as part of the workflow.\"\n    }\n  ],\n  \"pinData\": {},\n  \"connections\": {\n    \"ee413d6c-dad3-4e57-b08d-ffd0f84c682e\": {\n      \"main\": [\n        [\n          {\n            \"node\": \"error-handler-ee413d6c-dad3-4e57-b08d-ffd0f84c682e\",\n            \"type\": \"main\",\n            \"index\": 0\n          }\n        ],\n        [\n          {","sourceCodeStart":843,"sourceCodeEnd":879,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/workflows/Webhook/0453_Webhook_Code_Create_Webhook.json#L843-L879","documentation":"Thrown by 'Validate webhook signature' when $('Webhook to call for Slack command').first() has no binary property. Slack signature verification needs the RAW request body: the n8n Webhook node only stores the raw body as binary (default property 'data') when its 'Raw Body' option (rawBody: true, or 'Include Raw Body' in the UI) is enabled. Without it, item.binary is undefined and this guard fires before any HMAC check runs.","triggerScenarios":"Webhook node created without the raw-body option so Slack POSTs arrive with only parsed json (no binary.data), the binary property renamed, or a test invocation (e.g., from the editor 'test' URL with a manually crafted item) that never had binary. Also fires if an intermediate node stripped binary data.","commonSituations":"Recreating the webhook node and forgetting to tick 'Raw Body' (the single most common cause), n8n version upgrades resetting node options, or copying this verification code into a workflow whose webhook lacks the option.","solutions":["Open the 'Webhook to call for Slack command' node and enable Raw Body (set rawBody: true); retest with a real Slack request.","Confirm the binary property name is 'data' (default) or adjust the destructuring to the configured property name.","Guard with a clear message: if (!item.binary || !item.binary.data) throw new Error('Raw body missing: enable the Raw Body option on the webhook node.');","Verify with console.log(Object.keys(item.binary || {})) once working, then remove."],"exampleFix":"// before\nconst item = $('Webhook to call for Slack command').first();\nif (!item.binary) {\n  throw new Error('Missing binary data');\n}\nconst { binary: { data } } = item;\n\n// after\nconst item = $('Webhook to call for Slack command').first();\nif (!item.binary || !item.binary.data) {\n  throw new Error('Missing binary data: enable the \"Raw Body\" option on the webhook node so the raw Slack payload is stored as binary.');\n}\nconst { binary: { data } } = item;","handlingStrategy":"validation","validationCode":"const item = $('Webhook to call for Slack command').first();\nif (!item.binary || !item.binary.data) {\n  throw new Error('Missing binary data: enable the Raw Body option on the webhook node — Slack signature verification requires the exact raw payload.');\n}","typeGuard":"const hasRawBody = (item) =>\n  item?.binary?.data != null && typeof item.binary.data.data === 'string';","tryCatchPattern":"try {\n  verifySlackSignature(item, SIGNING_SECRET);\n} catch (e) {\n  // signature failures should be surfaced, never swallowed — this is a security control\n  throw new Error(`Slack signature verification failed: ${e.message}`);\n}","preventionTips":["Always enable Raw Body on webhook nodes whose payloads must be signature-verified (Slack, Stripe, GitHub).","Treat this error as a config defect, not a runtime flake: it means the raw body was never captured, so every request would fail.","Test the whole chain with a real Slack request after any webhook node recreation or n8n upgrade."],"tags":["n8n","slack","webhook","signature-verification","security","binary-data","hmac"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}