Claude API conversation history breaks after 2-3 messages - JSON escaping issue


I’m building a chat interface that connects to Claude’s API via API Connector. The chat works for 2-3 messages, then breaks. Claude loses all conversation history and starts fresh.

The Problem: After 2-3 exchanges, I get either:

  • “messages.X: all messages must have non-empty content” error

  • Blank screen with no response

  • Claude repeats its opening greeting (forgets entire conversation)

My Setup:

  • Storing conversation in a custom state (list of texts) on the page

  • Each message formatted as: {“role”: “user”, “content”: “message text”}

  • Passing to API as: chat’s Conversation join with “,”

  • Using :formatted as JSON-safe on content field

What I’ve Tried (all failed):

  1. Format as text with JSON-safe

  2. Manual find & replace for special characters

  3. Toolbox JavaScript for escaping

  4. Different quote/escape combinations

  5. Storing in database instead of custom state

Root Cause (I believe): Claude’s responses contain newlines, quotes, and special characters. Bubble’s text manipulation can’t properly escape these for valid JSON, especially inside :format as text.

What I Need: Multi-turn conversation with system prompt (I’m building a guided interview that asks ~10 questions). Need Claude to remember the full conversation history.

Questions:

  1. Has anyone successfully implemented multi-turn Claude chat with conversation history in Bubble?

  2. Is there a plugin that properly handles the messages array with JSON escaping?

  3. Any workarounds for the :format as text newline issue?

Thanks for any help!

Usually format as text with JSON-safe is the way to go. Just remember that it adds " " so if you have them, you will have to remove them when you add the JSON-safe formatting. :blush:

You’re almost there.

Basically each message should look exactly like this:

{“role”: “user/system”, “content”: {{message}} }

And then inside {{message}} you’ll have the actual message itself, and you should format it as JSON-safe. And in the list that you send to the LLM, you send this list joined with “,”

CleanShot 2026-01-22 at 13.13.50

CleanShot 2026-01-22 at 13.13.03

Can you send some screenshots so we can take a look?