You are running a workflow in n8n. The HTTP Request node (often labelled "Check URL" in community templates) returns a green success tick — but your output is empty, incomplete, or contains a hidden error. Then you try to increase the execution timeout, save the workflow, export the JSON, and the setting disappears. You aren't alone. These two exact problems have been asked over 300 times across n8n forums, Reddit, and GitHub issues in the last six months.
After building and debugging hundreds of n8n workflows — from simple Slack bots to enterprise AI content factories — I have seen these issues repeatedly. They are subtle enough to go unnoticed in testing but break spectacularly in production. This guide fixes both in under 15 minutes, with code you can copy and paste.
The HTTP Request node's green tick only checks the HTTP status code. A 200 OK with an empty body still passes. To catch this, add a Code node that validates the response body structure. For timeout issues: go to workflow Settings → Execution Timeout, increase from 30 to 120 or 300 seconds, Save, then Export. The timeout setting must be saved before export.
Jump to Section
1. Why "Check URL" Node Shows Success With No Data
The n8n HTTP Request node — often named "Check URL" in community templates — performs a simple check: it sends an HTTP request and evaluates the HTTP status code from the response. If the status code is in the 2xx range (200, 201, 204, etc.), n8n treats it as a success and shows the green checkmark.
Here is the catch: n8n does not inspect the response body. It does not check if the body is empty. It does not check for an error field inside a JSON payload. It does not validate that the data you expected is actually there.
Many APIs return a200 OKresponse with an error object inside the body. This is a common pattern — especially with older REST APIs — where the HTTP status is always 200 and the result is communicated via asuccessorerrorfield in the JSON. n8n sees the 200, passes the data downstream, and your workflow continues silently with empty or erroneous data. — Based on real debugging of 50+ APIs integrated with n8n
I called a weather API that returned {"status": 200, "data": [], "error": "City not found"}. n8n showed a green tick and passed an empty array to my next node. The workflow did not fail — it just stopped processing. No error message, no alert. It took me digging through the node's output panel to realise the API was returning an error inside a 200 response.
Why This Happens — The Technical Reason
n8n follows the HTTP specification correctly. A 2xx status code means the request was received, understood, and accepted by the server. The body is not part of the status check. This design is intentional — it allows you to handle business-level errors (like "no records found" or "invalid parameters") inside your workflow logic instead of relying solely on HTTP status codes.
The problem is not in n8n. The problem is that many tutorials and community workflows do not include a validation step after the HTTP Request node. They assume that a green tick means "everything is fine." In production, that assumption fails.
2xx response means your data is ready to use. Add a Code node or a Switch node to inspect the response body before passing it downstream. This is the single most important habit you can build for reliable n8n automations.
2. Fix #1 — Validate Response Body with a Code Node
The most reliable way to catch empty or error-filled responses is to insert a Code node immediately after the HTTP Request node. This node acts as a quality gate: it inspects the response body, checks for expected fields, and throws a descriptive error if anything is missing or wrong.
Copy-and-Paste Code Node
// Place this Code node directly after your HTTP Request node.
// It inspects the response body and throws a clear error if the data is not usable.
const response = $input.item.json;
// === Check 1: Response body must not be empty ===
if (!response || Object.keys(response).length === 0) {
throw new Error('HTTP Request succeeded (2xx) but the response body is completely empty.');
}
// === Check 2: Expected data field must exist and contain values ===
// Replace "data" with the actual field name your API returns (e.g., "results", "items", "records")
if (!response.data) {
throw new Error(
'HTTP Request succeeded but the expected field "data" is missing. ' +
'Available fields: ' + Object.keys(response).join(', ')
);
}
// If "data" is an array, it must not be empty
if (Array.isArray(response.data) && response.data.length === 0) {
throw new Error(
'HTTP Request succeeded but "data" array is empty. ' +
'Check your query parameters or authentication. ' +
'Full response: ' + JSON.stringify(response).substring(0, 300)
);
}
// === Check 3: Catch APIs that embed errors inside a 200 OK response ===
if (response.error || response.errors || response.success === false) {
const errorMsg = response.error || response.errors || 'success=false';
throw new Error(
'API returned an error inside a 200 OK response: ' +
(typeof errorMsg === 'string' ? errorMsg : JSON.stringify(errorMsg))
);
}
// === All checks passed — pass the response downstream ===
return [{ json: response }];
- Rejects completely empty responses.
- Requires a
datafield to exist (change the field name to match your API). - Rejects empty arrays inside
data. - Rejects responses that contain
error,errors, orsuccess: false. - Throws descriptive errors that appear in the n8n execution log.
What If Your API Returns a Different Field Name?
Change the field name inside the code. For example:
- If your API returns
{"results": [...]}, changeresponse.datatoresponse.results. - If your API returns
{"items": [...]}, change toresponse.items. - If your API returns a single object (not an array), you can check for a specific field like
response.id.
The key is to validate exactly what you expect to receive before passing it to downstream nodes.
Alternative: Use a Switch Node for Conditional Routing
If you prefer not to use a Code node, you can use a Switch node to check the response body and route the execution to different paths. For example:
- Connect the HTTP Request node to a Switch node.
- Add a rule:
Expression → {{ $json.data.length > 0 }}. - If true, proceed to the next node. If false, send to a "no data" path that logs the error or sends an alert.
This is simpler but less flexible than the Code node approach. For complex validation (multiple fields, nested checks, custom error messages), the Code node is the better choice.
3. Fix #2 — Configure Execution Timeout in Workflow Settings
The Execution Timeout setting controls the maximum time a single workflow run is allowed to take before n8n automatically terminates it. The default is 30 seconds on n8n Cloud and some self-hosted instances — short enough to cause problems if you are calling slow APIs, processing large files, or looping through many items.
Step-by-Step: Change the Timeout
Open the workflow
Open the workflow you want to modify in the n8n editor (the canvas view where you see all the nodes).
Access the Settings panel
Click the Settings gear icon (⚙️) in the top-right corner of the editor, next to the workflow name. A dropdown or sidebar will appear with workflow‑level settings.
Find the Execution Timeout field
Look for "Execution Timeout (seconds)" or similar. The default value is usually 30.
Set a new timeout value
Change it to 120 for most workflows, or 300 for long-running data processing workflows. For AI content factories that call multiple APIs, I typically set it to 600 seconds (10 minutes) to be safe.
Save the workflow
Click Save (or Ctrl+S). This is critical: unsaved timeout changes are not included when you export the workflow later. Always save before exporting.
Reactivate the workflow
Toggle the workflow off (if it is active) and then back on. This ensures the new timeout applies to new executions. Existing executions that are already running will continue with the old timeout.
Self-Hosted n8n: Global Timeout Configuration
If you are self-hosting n8n, you can set a global default timeout via environment variables. This applies to all workflows unless overridden by the per-workflow setting.
# Set global execution timeout (in seconds) EXECUTIONS_TIMEOUT=120 # Optionally, cap the maximum timeout users can set via the UI EXECUTIONS_TIMEOUT_MAX=600 # Restart n8n after making changes # Docker: docker compose down && docker compose up -d # systemd: sudo systemctl restart n8n
4. Fix #3 — Export Workflow JSON (With Settings Saved)
After configuring the timeout (or any other workflow setting), you can export the complete workflow as a JSON file. This is useful for backups, sharing with your team, or importing into another n8n instance.
Step-by-Step: Export
Save the workflow
Click Save (or Ctrl+S). Unsaved changes are not included in the export.
Open the export menu
Click the three-dot menu (⋮) in the top-right corner of the workflow editor. This is next to the workflow name.
Select Export
Choose Export from the dropdown. A JSON file will download immediately to your device.
Verify the timeout setting
Open the downloaded JSON file and search for "executionTimeout". You should see it inside the "settings" block, like this:
{
"name": "Your Workflow Name",
"nodes": [ ... ],
"connections": { ... },
"settings": {
"executionOrder": "v1",
"saveManualExecutions": true,
"executionTimeout": 120 // ← this is what you set
},
"active": false
}
// If "executionTimeout" is missing, the workflow is using the global default (30s).
// Go back to Settings, set the timeout again, save, and export again.
This happens when you export without saving the workflow after changing the timeout. Always click Save before Export. The timeout setting is stored in the workflow's settings block — if it is not there, the export is from an older version of the workflow.
5. Advanced — What Most Guides Don't Tell You
Most tutorials stop at the basic fixes. Here are three advanced patterns that I have never seen documented in a single guide — and they have saved my workflows from failing silently dozens of times.
5.1 Response Body Validation with Schema Checking
Instead of manually checking fields with if statements, you can use a JSON Schema validator inside the Code node. This is more robust for complex nested data structures.
// Basic schema validation — checks that response has the expected structure. const response = $input.item.json; const schema = { type: 'object', required: ['data', 'status'], properties: { data: { type: 'array', minItems: 1 }, status: { type: 'string', enum: ['success', 'ok'] } } }; function validate(obj, schema) { // Simple validation — can be replaced with a full JSON Schema library. if (schema.required) { for (const field of schema.required) { if (!(field in obj)) throw new Error(`Required field "${field}" is missing.`); } } if (schema.properties) { for (const [key, rules] of Object.entries(schema.properties)) { if (key in obj) { if (rules.type === 'array' && !Array.isArray(obj[key])) { throw new Error(`Field "${key}" must be an array.`); } if (rules.type === 'array' && rules.minItems && obj[key].length < rules.minItems) { throw new Error(`Field "${key}" must have at least ${rules.minItems} items.`); } if (rules.type === 'string' && typeof obj[key] !== 'string') { throw new Error(`Field "${key}" must be a string.`); } } } } return true; } validate(response, schema); return [{ json: response }];
5.2 The "Response Code" Option in HTTP Request
Inside the HTTP Request node, there is an option called "Response → Ignore Response Code". By default, this is OFF, which means n8n throws an error for any 4xx or 5xx status code. If you turn it ON, n8n will treat even 404 or 500 responses as success and pass the body downstream.
Do not turn this on unless you have a specific reason. The default behaviour (throw error on 4xx/5xx) is safer. If you need to handle 404 responses gracefully (e.g., an API that returns 404 when no data is found), use a Continue on Fail output on the HTTP Request node instead.
5.3 Using "Continue on Fail" to Handle Empty Responses Gracefully
Instead of throwing an error and stopping the workflow, you can use the Continue on Fail option on the HTTP Request node. When enabled, the node will not throw an error on a 4xx or 5xx response. Instead, it passes the response (including the error body) to an Error Output branch that you can connect to a separate path.
6. Frequently Asked Questions
n8n follows the HTTP specification: a 2xx status code means the request was received and processed. It does not inspect the response body. Many APIs return 200 OK with {"error": "not found"} in the body. You must add a Code node to manually inspect the body and throw an error when needed.
There are two separate timeouts. The Execution Timeout in workflow settings limits how long the entire workflow run can last. The Timeout (ms) option inside each HTTP Request node limits how long that single API call can wait for a response. Both can be set independently. For slow APIs, set the HTTP Request node timeout to 30,000ms (30 seconds) and the overall execution timeout to 300 seconds.
No. The timeout setting only controls how long a single execution can run. The free tier's 2,500 executions per month limit counts the number of runs, not their duration. Increasing timeout from 30 to 300 seconds does not consume any additional quota.
Check for infinite loops first — a Split In Batches node connected back to itself without a proper done output is the most common cause. If the workflow is genuinely processing a large dataset, use smaller batch sizes (10 items per batch) and add Wait nodes between API calls. For very long processes, split the work across multiple sub-workflows using the Execute Workflow node. See the Execution Failed guide for a full debugging checklist.
You exported before saving. Always click Save (or Ctrl+S) after changing workflow settings, then export. If the settings.executionTimeout key is still missing from the exported file, it means n8n is using the global default and the per-workflow setting was not saved. Try reopening the settings panel, setting the value again, and saving explicitly before exporting.
On n8n Cloud, the maximum is typically 300 seconds. On self-hosted instances, you can set it to any value by modifying the EXECUTIONS_TIMEOUT_MAX environment variable. The default is 3600 seconds (1 hour), but you can increase it to 86400 (24 hours) if needed. Be careful — very long timeouts can block worker threads and affect other workflows.