{ "nodes": [ { "parameters": { "url": "=https://newsapi.org/v2/everything?apiKey={{ $('Setup1').first().json.apiKey }}&q={{ $json.output.clean_company_name }}&from={{ DateTime.now().minus({ days: $('Setup1').first().json.newsAge }).toF

The problem is that clean_company_name is not in the current node’s $json because the node that creates it is not in the same execution path (branch), so n8n drops the data and it becomes undefined. However I can’t seem to fix the problem
There is no error message, just the data isn’t getting sent properly into the gmail

In the ‘Edit Fields’ node it reads:

This is an AI answer:

Here’s the core issue and how to fix it from the support thread you linked (topic: “HTTP Request to NewsAPI not pulling clean company name + dynamic date”): (n8n Community)


:white_check_mark: Problem Summary (from your thread)

Your HTTP Request node’s URL expression looked something like:

=https://newsapi.org/v2/everything?apiKey={{ $('Setup1').first().json.apiKey }}&q={{ $json.output.clean_company_name }}&from={{ DateTime.now().minus({ days: $('Setup1').first().json.newsAge }).toF...

…but clean_company_name wasn’t actually in the current node’s JSON because the node that creates it wasn’t in that exact execution path/branch. n8n drops values that aren’t in the active branch, so the expression became undefined — which breaks the URL you’re trying to send. (n8n Community)


:white_check_mark: Fix: Ensure the Data is in the HTTP Request Node

1. Bring the node that generates clean_company_name into the same path as the HTTP Request

In n8n, expressions like {{ $json.field }} only work if the node is directly before your HTTP Request node in the same branch. If you’re branching (IF / SplitInBatches / multiple paths), n8n forgets fields that aren’t on that exact path.

Solution:
:check_mark: Connect the node that produces clean_company_name (e.g., your Edit Fields / Set / Function node) directly to the HTTP Request, or
:check_mark: Use a Merge node to combine branches so the value is available where you need it.

Example flow:

Trigger → Fetch Data → Clean Company Name → HTTP Request → …

This ensures the HTTP Request node has access to clean_company_name in its input item JSON.


2. Use toISO() for dynamic date strings

Your expression for the date portion must return a proper ISO date string. If you want today minus X days:

={{ DateTime.now().minus({ days: $('Setup1').first().json.newsAge }).toISO() }}

:check_mark: .toISO() returns a correctly formatted date string (e.g., 2026-01-01T00:00:00.000Z) that works in query params. (n8n Docs)


3. Clean up your URL parameter layout

Instead of writing your full URL as a single long expression, split it into query parameters in the HTTP Request node — this avoids concatenation mistakes and makes debugging easier.

Example HTTP Request settings:

  • Method: GET
  • URL: https://newsapi.org/v2/everything
  • Query Parameters:
    • apiKey: ={{ $('Setup1').first().json.apiKey }}
    • q: ={{ $json.output.clean_company_name }}
    • from: ={{ DateTime.now().minus({ days: $('Setup1').first().json.newsAge }).toISO() }}

This method prevents malformed URLs because n8n builds the query string for you.


:hammer_and_wrench: Why It Was Undefined

:right_arrow: n8n doesn’t carry all fields across workflow branches — only the ones flowing through that specific path. If clean_company_name is calculated in a node that isn’t upstream of the HTTP Request node you’re trying to use, then $json.output.clean_company_name evaluates to undefined. (n8n Community)


Quick Checklist Before You Test Again

:white_check_mark: Confirm the node that outputs clean_company_name goes into the HTTP Request node
:white_check_mark: Use toISO() for formatting dates correctly
:white_check_mark: Prefer HTTP Request Query Parameters instead of long URL concatenation
:white_check_mark: Test the value of each expression by clicking Preview in the expression editor


If you want, you can share your workflow JSON and I can rewrite your HTTP Request node properly so it works end-to-end.

Source: ChatGPT - N8N Assistant (By Nskha)

Thank you for the guidance @Nskha However the results are still not given into my gmail, as it still reads “undefined” on Latest news {{ $(‘Get latest news’).item.json.articles }} in the Edit Fields node. maybe it is better if you see my full workflow:

First, you exposed your OpenRouter API key; I strongly recommend revoking the generated token immediately: Bearer sk-or-v1-46772b30d7-------e0abb4e0f2653be81664. Do the same for any other keys and the email listed in the config. Next, you should contact our ChatGPT plugin for help with your setup: ChatGPT Free - N8N Assistant (By Nskha). Revoke the keys right away, you can’t remove this content from the community now, and it’s already been indexed. After you’ve done that, I can review your workflow if you still can’t get it working with GPT’s assistance.

i will review your workflow now; but until then immediately go and revoke your keys

I’m aware of that, I revoked my keys already. Thank you for reminding me

the reply of a.i was having some deprecated keys for time.

However the path you can use for
{{ $(‘Get latest news’).item.json.articles }}
is
{{ $item("0").$node["Get latest news"].json["articles"] }} or {{ $node["Get latest news"].json["articles"] }}

I asked A.I to improve the workflow into better version and here’s the results i would recommend testing it as it instead as it can handle multiple items of news:

Report:

Company Intelligence Report - n8n Workflow Template

Production-ready workflow that generates automated intelligence reports for companies in your calendar meetings.

Key Improvements from Original

Fixed Bugs

Issue Original Fixed
Broken date expression toISO() }}toFormat (syntax error) $now.minus({days: X}).toFormat('yyyy-MM-dd')
Deprecated $items() $items().length $input.all().length
Multiple articles ignored Single item handling Proper array iteration in Code node
Exposed API keys Hardcoded in JSON Environment variables ($env.NEWS_API_KEY)
Unused config emails Hardcoded recipient $('Config').first().json.emailRecipients

New Features

  • Error handling: All external API nodes have continueOnFail: true
  • AI executive summary: Generates meeting prep summary via OpenRouter
  • Proper news formatting: Markdown-formatted email with article details
  • Environment variable support: Secure credential management
  • Better filtering: Added “Sync with” prefix, null-safe expressions
  • Skip paths: Clear NoOp nodes for debugging filtered items

Workflow Structure

Daily @ 7 AM
    ↓
Config (load settings)
    ↓
Get Today's Meetings (Google Calendar)
    ↓
Has Meetings? ─── No ──→ [End]
    ↓ Yes
Filter Company Meetings (Call/Meeting/Sync with...)
    ↓ Match
Extract Company Name (AI Agent + OpenAI)
    ↓
Valid Company? ─── No ──→ [Skip]
    ↓ Yes
Fetch Company News (NewsAPI)
    ↓
Format News Report (Code Node)
    ↓
Generate AI Summary (OpenRouter)
    ↓
Build Final Email (Code Node)
    ↓
Send Report Email (Gmail)

Configuration

Required Environment Variables

NEWS_API_KEY=your_newsapi_key
OPENROUTER_API_KEY=your_openrouter_key  # Optional, for AI summaries
[email protected]

Required Credentials

  1. Google Calendar OAuth2 - Calendar access
  2. Gmail OAuth2 - Email sending
  3. OpenAI API - Company name extraction

Config Node Defaults

Edit the “Config” node to change:

  • newsAgeDays: How far back to search (default: 10)
  • maxArticles: Max articles per company (default: 20)

Expression Fixes Applied

Date Expression

// ❌ Original (broken)
&from={{ DateTime.now().minus({ days: ... }).toISO() }}toFormat('yyyy-MM-dd') }}

// ✅ Fixed
{{ $now.minus({ days: $('Config').first().json.newsAgeDays }).toFormat('yyyy-MM-dd') }}

Item Count Check

// ❌ Original (deprecated)
{{ $items().length }}

// ✅ Fixed  
{{ $input.all().length }}

Null-Safe Field Access

// ❌ Original (can throw)
{{ $json.summary.toLowerCase() }}

// ✅ Fixed
{{ $json.summary?.toLowerCase() ?? '' }}

Code Node: Format News Report

Handles the NewsAPI response array properly:

const articles = newsResponse.articles || [];

const formattedArticles = articles.map((article, index) => {
  const publishedDate = article.publishedAt 
    ? new Date(article.publishedAt).toLocaleDateString('en-US', {...})
    : 'Unknown date';
  
  return `### ${index + 1}. ${article.title || 'Untitled'}\n...`;
}).join('\n\n---\n\n');

Installation

  1. Import company-intelligence-report.n8n into n8n
  2. Set environment variables or edit Config node
  3. Update credential IDs:
    • YOUR_CALENDAR_CRED_ID
    • YOUR_GMAIL_CRED_ID
    • YOUR_OPENAI_CRED_ID
  4. Test with manual trigger
  5. Activate workflow

License

MIT - Use and modify freely.

Hi @naosocool

It’s me again :slight_smile:

To solve this in a practical way, first fix the broken references. Make sure the nodes named Setup1 and Normalize company name actually exist with those exact names, or update the expressions to match the current node names.

Then ensure the data is flowing through the correct path. The sequence Normalize company name > Get latest news > Edit Fields > Gmail must be in the same branch of the workflow. If they are on different branches, add a Merge node before Edit Fields to combine companyName and articles into a single stream.

In the Edit Fields node, set “Latest news” as a fixed field name and put the expression in the value field, not in the field name. If you are working with only one item, use something like {{ $node["Get latest news"].json.articles }} (or first() if you are dealing with multiple items). You need to make sure the node that builds the email has access to the data; once these steps are followed, the undefined value will disappear.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.