{"record":{"id":"6d35d96bf6358ba2","repo":"Zie619/n8n-workflows","slug":"html-body-is-undefined-check-the-previous-node-s","errorCode":null,"errorMessage":"HTML body is undefined. Check the previous node's output.","messagePattern":"HTML body is undefined\\. Check the previous node's output\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"workflows/Code/1802_Code_Manual_Import_Webhook.json","lineNumber":76,"sourceCode":"              \"name\": \"User-Agent\",\n              \"value\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/91.0.4472.124\"\n            }\n          ]\n        }\n      },\n      \"typeVersion\": 4.2,\n      \"notes\": \"This httpRequest node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"734a5304-f67f-4ace-a1da-0d268664452c\",\n      \"name\": \"Scrape raw video URL\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"position\": [\n        480,\n        20\n      ],\n      \"parameters\": {\n        \"jsCode\": \"const html = $input.first().json.data;\\nconst headers = $input.first().json.headers || {};\\nconst cookies = headers['set-cookie'] || [];\\n\\nif (!html) {\\n  throw new Error(\\\"HTML body is undefined. Check the previous node's output.\\\");\\n}\\nconst regex = /<script id=\\\"__UNIVERSAL_DATA_FOR_REHYDRATION__\\\" type=\\\"application\\\\/json\\\">([\\\\s\\\\S]*?)<\\\\/script>/;\\nconst match = html.match(regex);\\n\\nif (match) {\\n  const jsonStr = match[1];\\n  const data = JSON.parse(jsonStr);\\n  const videoUrl = data?.__DEFAULT_SCOPE__?.[\\\"webapp.video-detail\\\"]?.itemInfo?.itemStruct?.video?.playAddr;\\n  if (!videoUrl) {\\n    throw new Error(\\\"Could not find video URL in the JSON data.\\\");\\n  }\\n  return [{ json: { videoUrl, cookies: cookies.join('; ') } }];\\n} else {\\n  throw new Error(\\\"Could not find __UNIVERSAL_DATA_FOR_REHYDRATION__ script in the HTML.\\\");\\n}\"\n      },\n      \"typeVersion\": 2,\n      \"notes\": \"This code node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"f574ccb8-6f5f-4e55-a2d5-7ad775d3c4e5\",\n      \"name\": \"Output video file without watermark\",\n      \"type\": \"n8n-nodes-base.httpRequest\",\n      \"position\": [\n        900,\n        20\n      ],\n      \"parameters\": {\n        \"url\": \"{{ $env.BASE_URL }}\",\n        \"options\": {\n          \"response\": {\n            \"response\": {\n              \"responseFormat\": \"file\"","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/workflows/Code/1802_Code_Manual_Import_Webhook.json#L58-L94","documentation":"Thrown by the 'Scrape raw video URL' Code node in a TikTok video-download workflow. The node expects the previous HTTP Request node to expose the page HTML under json.data. When that field is undefined (request failed, response shape differs, or the HTTP node put the body under a different key), the guard fires before any regex scraping happens.","triggerScenarios":"The upstream HTTP Request node returned an error response or was configured with responseFormat 'autodetect'/'json' so the raw body is not at json.data; the request was blocked (403/captcha) and returned an error object; the response property name differs (e.g. json.body, json.data.body for n8n's full-response option).","commonSituations":"HTTP node 'Response Format' set to JSON instead of Text/String; 'Include Response Headers and Status' toggled, nesting the body under data.body; TikTok blocking the request (bot detection, missing User-Agent) so the body is empty; workflow imported from another instance where the HTTP node version/options differ.","solutions":["Check the upstream HTTP Request node's execution output to see where the HTML actually landed (json.data vs json.body vs json.data.body).","Set the HTTP node Response Format to 'Text/String' (or 'autodetect' with the body expected as a string) so the HTML arrives as json.data.","Add a User-Agent header and verify the request returns 200 — a 403/captcha page will still be defined but fail later scraping, while a rejected request can yield undefined.","Guard with a clearer message that dumps Object.keys($input.first().json) to diagnose shape drift."],"exampleFix":"// before\nconst html = $input.first().json.data;\nif (!html) {\n  throw new Error(\"HTML body is undefined. Check the previous node's output.\");\n}\n\n// after\nconst first = $input.first().json;\nconst html = first.data ?? first.body ?? first.data?.body;\nif (typeof html !== 'string' || html.length === 0) {\n  throw new Error(`HTML body is undefined. Available keys: ${Object.keys(first).join(', ')}`);\n}","handlingStrategy":"type-guard","validationCode":"const first = $input.first().json;\nconst html = first.data ?? first.body ?? first.data?.body;\nconst ok = typeof html === 'string' && html.length > 0;","typeGuard":"function hasHtmlBody(j) {\n  const b = j?.data ?? j?.body ?? j?.data?.body;\n  return typeof b === 'string' && b.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Set the upstream HTTP node's Response Format to Text so the body lands at json.data as a string.","Send browser-like headers (User-Agent) so the target returns real HTML.","Check the HTTP node's own 'on fail' setting — fail there with its status code, not later in the parser.","Log Object.keys of the input json whenever shape drift is possible."],"tags":["n8n","http-request","web-scraping","tiktok","response-shape"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}