Gmail Node Error (v1.86.1): 'Invalid id value' with Expression {{ $json.id }}, but OK Hardcoded

I’m trying to build a workflow to bulk mark unread Gmail emails as read, but I’m hitting a persistent error on the step that modifies the email.

Goal:
Find unread emails in the inbox and mark them as read.

Setup:

  • N8N Version: 1.86.1 (Cloud)

  • Gmail Node Version: 2.1 (Latest)

  • Node 1: Gmail Node

    • Operation: Get Many

    • Resource: Message

    • Filters: Read Status: Unread emails only AND Label IDs Contains INBOX

    • Limit: Set to a batch size (e.g., 150)

  • Node 2: Gmail Node

    • Operation: Tried both Mark as Read and Remove Label

    • Resource: Message

    • Message ID: Using Expression ={{ $json.id }} (or variants)

    • Label Names or IDs (for Remove Label): UNREAD

Problem:
Node 1 successfully retrieves the unread emails. The output table clearly shows the message id (e.g., 196255541640182a).

However, Node 2 consistently fails with the error:
ERROR: Bad request - please check your parameters (item 0)
Invalid id value
(From Gmail: { “error”: { “code”: 400, “message”: “Invalid id value”, “errors”: [ { “message”: “Invalid id value”, “domain”: “global”, “reason”: “invalidArgument” } ], “status”: “INVALID_ARGUMENT” } })

This error occurs when the Message ID field uses the expression ={{ $json.id }}. The expression preview shows the correct ID value before failing.

Troubleshooting Steps Taken:

  1. Verified Node 1 output contains the correct id field.

  2. Tried Node 2 Operation Mark as Read with Message ID ={{ $json.id }} → Fails.

  3. Tried Node 2 Operation Remove Label with Label UNREAD and Message ID ={{ $json.id }} → Fails.

  4. Tried adding .toString() to the expression: ={{ $json.id.toString() }} → Fails.

  5. Tried using the threadId just in case: ={{ $json.threadId }} / ={{ $json.threadId.toString() }} → Fails.

  6. Tried running the full workflow vs. “Test step” → Fails both ways.

  7. Deleted and recreated the Gmail OAuth2 credentials, ensuring all permissions were granted → Fails.

  8. Crucially: If I switch Node 2’s “Message ID” field to Fixed mode and paste the exact same ID (copied from Node 1’s output) directly into the field, the “Remove Label” operation SUCCEEDS for that specific message.

Conclusion:
Since the operation works perfectly with a hardcoded ID but fails consistently when using the {{ $json.id }} expression (even though the value appears correct), it seems the issue lies specifically with how the expression-derived value is being passed to the API by this version of the node.

I found this related thread (https://community.n8n.io/t/gmail-ai-agent-read-messages-and-mark-them-as-read/73926/2) which confirms the “Remove Label” UNREAD method with ={{ $json.id }} should be the correct approach.

Is this a known issue with N8N v1.86.1 / Gmail Node v2.1, or is there anything else I might be missing? Any insights would be greatly appreciated!

Thanks!

Hello and welcome to the community!

Please post your workflow using the </> button.

If you put this exact string into the field this might be a problem. You do not need to add the = character in Expression mode.

If this resolves your question, please mark this post as a :white_check_mark: Solution.

Hi, I’m encountering the same issue on version 1.92.1. Have you found a fix or workaround?

{
  "error": {
    "code": 400,
    "message": "Invalid id value",
    "errors": [
      {
        "message": "Invalid id value",
        "domain": "global",
        "reason": "invalidArgument"
      }
    ],
    "status": "INVALID_ARGUMENT"
  }
}

Same error here for addLabels. I’m running a loop through emails retrieved with a search. The addLabels always fails on the second message. The next run, that message is the first (because search excludes messages with the label I’m trying to assign), and the addLabels call works just fine… once.