Critical Bug: "JSON parameter needs to be valid JSON" with any dynamic expression in HTTP Request Body

Hello n8n Community,
I am reporting a critical and reproducible bug where the HTTP Request node consistently fails with a JSON parameter needs to be valid JSON error, whenever I try to use an expression to set the body.
This issue occurs on multiple, independent n8n instances, including a brand new, clean n8n cloud account, and a self-hosted instance on Hostinger.
My Environment:

  • n8n Version: Latest on n8n Cloud (and also tested on self-hosted 1.113.3)
  • Database: SQLite (Default)
  • Running n8n via: Docker (self-hosted) and n8n Cloud.
    Minimal Reproducible Example:
    Here is the simplest possible workflow that demonstrates the bug. It uses only two core nodes.
    Node 1: Code Node
    This node creates a simple, valid JavaScript object.
    Code:
    return [{ json: { my_data: { user: "test", id: 123 } } }];
    Node 2: HTTP Request Node
    This node attempts to send the object from the first node as its body to a public test endpoint.
  • Method: POST
  • URL: (I used a webhook.site URL to test)
  • Send Body: ON
  • Body Content Type: JSON
  • Specify Body: Using JSON
  • JSON field (The Failing Expression): ={{ $json.my_data }}
    Expected vs. Actual Behavior:
  • Expected Behavior: The HTTP Request node should successfully send the JSON body {"user":"test","id":123}.
  • Actual Behavior: The node fails immediately with the error JSON parameter needs to be valid JSON.
    Crucial Troubleshooting Information:
  • Static JSON works perfectly: If I replace the expression ={{ $json.my_data }} with a hardcoded static JSON string {"user":"test","id":123}, the request is sent successfully. This proves that the destination URL and network are all fine.
  • Workarounds also fail: I have also tried creating a JSON string in the Code node using JSON.stringify() and passing it to the HTTP Request node’s Expression field. This also results in the same error.
    Conclusion:
    This seems to be a fundamental bug in how the n8n expression engine passes evaluated data to the HTTP Request node’s body parameter. This is a critical issue as it prevents the creation of any dynamic POST requests.
    Could the team please look into this?
    Thank you for your help.

Describe the problem/error/question

What is the error message (if any)?

Please share your workflow

(Select the nodes on your canvas and use the keyboard shortcuts CMD+C/CTRL+C and CMD+V/CTRL+V to copy and paste the workflow.)

Share the output returned by the last node

Information on your n8n setup

  • n8n version:
  • Database (default: SQLite):
  • n8n EXECUTIONS_PROCESS setting (default: own, main):
  • Running n8n via (Docker, npm, n8n cloud, desktop app):
  • Operating system:

I tried to reproduce what you explained, but never got an error:

Works fine here.
This is because you are using = in the expression i believe, should just be:

{{ $json.my_data }}

={{ $json.my_data }} - The = prefix tells n8n to evaluate the expression and convert the result to a string. When JavaScript converts an object to a string, it produces [object Object] by default.

{{ $json.my_data }} - Without the =, n8n passes the actual object through as-is, preserving its structure as a JSON object.

I am having the same problem and i tried without = and same issue I am also using a self hosted n8n. I ran it through json linter and its valid but doesn’t output a valid JSON. I also updated to the latest version and no luck. I tried multiple endpoints from different providers. I tried to run a code node and stingify still no luck. I am postgres db, I am very new to this so I don’t know if I am doing something wrong. I built a mcp server for claude and let him have a crack at it and he gave up so did gemini. Chatgpt keeps trying to change it to raw and add a set node but i don’t see a set node anywhere so I am going to agree with Kamall there something wrong with it.