Hello N8N Community,
I am building an AI Agent workflow with the following setup:
Workflow Structure:
- Telegram Trigger → AI Agent (SAI BRAIN) → Telegram Send Message
- AI Agent connected to: Anthropic Claude Sonnet 4.5 + Postgres Chat Memory
Database:
- Supabase Free tier — South Asia Mumbai region
- Table name: n8n_chat_histories
- Columns: id (int8), created_at (timestamptz), session_id (text), message (text)
- RLS is DISABLED
Connection Method:
- Session Pooler (IPv4 compatible)
- Host: aws-1-ap-south-1.pooler.supabase.com
- Port: 5432
- Database: postgres
- SSL: Disabled
- Connection test: Shows “Connection tested successfully”

Postgres Chat Memory Node Settings:
- Session ID: Connected Chat Trigger Node
- Session Key: {{ $json.sessionId }}
- Table Name: n8n_chat_histories
- Context Window Length: 10
Error Message:
Got unexpected type: undefined
(appears in Postgres Chat Memory sub-node every time)
What I Have Tried:
- Session ID “Define below” with {{ $json.message?.chat?.id ?? $json.sessionId }}
- Session ID with {{ String($json.message?.chat?.id ?? $json.sessionId) }}
- Added Edit Fields node before AI Agent to inject sessionId field
- Changed SSL from Disable to Require
- All attempts result in same error
Important Note:
Workflow works perfectly with Simple Memory node.
Only Postgres Chat Memory fails consistently.
N8N Version: 2.9.4 Cloud
What is the standard correct way to connect Postgres Chat Memory
to Supabase when triggered by Telegram?
Thank you!
Hi @gcpandey Welcome!
have you tried dropping the n8n chat history table? like n8n_chat_histories table in supabase so that n8n can re create it , and try using the session key "{{ $('Telegram Trigger').item.json.message.chat.id }}" and yah wrapped in quotes so that it is forced as a string, let me know if that works.
two things to fix here:
1. Session ID — you’re using Telegram Trigger, not Chat Trigger, so “Connected Chat Trigger Node” won’t work. in the Postgres Chat Memory node, set Session ID to Define below and use:
{{ $(‘Telegram Trigger’).item.json.message.chat.id.toString() }}
the .toString() is important — Telegram chat IDs are integers, and Postgres Chat Memory expects a string.
2. Session Pooler incompatibility — this is likely the real cause of “Got unexpected type: undefined”. Supabase’s Session Pooler (port 5432) doesn’t play well with how n8n’s Postgres Chat Memory node handles type casting. switch to the Direct Connection instead:
- in Supabase go to Settings → Database → Connection string → select Direct connection (not pooler)
-
- use port
5432 with the direct host (format: db.xxxxxxxxxxxx.supabase.co)
- if direct connection isn’t available on free tier due to IPv6, try the Transaction Pooler on port
6543 — it handles type mapping better than Session Pooler for this use case.
Welcome to the community @gcpandey!
This specific error “Got unexpected type: undefined” in the Postgres Chat Memory node is almost always a type-casting issue between n8n’s internal logic and how the Postgres driver handles the session ID, especially when using a pooler.
Since you mentioned you are on the Supabase Free tier, you are likely hitting an IPv6 vs IPv4 compatibility issue with the direct connection.
Try these three things in order:
-
Force String Type in Session ID: Even though you tried , sometimes the expression evaluator in n8n can be tricky. In your Postgres Chat Memory node, set Session ID to Define below and use:
Make sure you aren’t referencing if that’s coming from a previous node that might not be passing it correctly. Use the direct reference from the Telegram Trigger.
-
Switch to Transaction Pooler (Port 6543): You mentioned using the Session Pooler on port 5432. Supabase’s Session Pooler can sometimes keep state that interferes with the specific way n8n opens/closes memory connections. Switch the port to 6543 and the mode to Transaction in your Supabase dashboard.
-
Check the Table Schema: Ensure your column in Supabase is actually or . If it’s accidentally an or another type, the node will throw an ‘undefined’ type error because it can’t map the incoming string to the column.
Since Simple Memory works, your workflow logic is fine—this is 100% down to the database handshake!