Problem in node ‘Basic LLM Chain‘ Single '}' in template. Can't escape

Hi I’m trying to put the following piece of text into my llm-chain:


"response": {

"text": "How to Use JSON and XML in API Data Formats"


"title": "Data Formats",

"text": "Data Formats\nSo far, we've learned that HTTP (Hyper-Text Transfer Protocol) is the\nunderpinning of APIs on the web and that to use them, we need to know how\nHTTP works. In this chapter, we explore the data APIs provide, how it's\nformatted, and how HTTP makes it possible.\nRepresenting Data\nWhen sharing data with people, the possibilities for how to display the\ninformation is limited only by human imagination. Recall the pizza parlor\nfrom last chapter — how might they format their menu? It could be a text-\nonly, bulleted list; it could be a series of photos with captions; or it could\neven be only photos, which foreign patrons could point at to place their order.\nA well-designed format is dictated by what makes the\ninformation the easiest for the intended audience to\nunderstand.\nThe same principle applies when sharing data between computers. One\ncomputer has to put the data in a format that the other will understand.\nGenerally, this means some kind of text format. The most common formats\nfound in modern APIs are JSON (JavaScript Object Notation) and XML\n(Extensible Markup Language).\nJSON\nMany new APIs have adopted JSON as a format because it's built on the\npopular Javascript programming language, which is ubiquitous on the web\nand usable on both the front- and back-end of a web app or service. JSON is a\n\nvery simple format that has two pieces: keys and values. Keys represent an\nattribute about the object being described. A pizza order can be an object. It\nhas attributes (keys), such as crust type, toppings, and order status. These\nattributes have corresponding values (thick crust, pepperoni, and out-for-\ndelivery).\nLet's see how this pizza order could look in JSON:\n<<_OPEN_{_>>\n\"crust\": \"original\",\n\"toppings\": [\"cheese\", \"pepperoni\", \"garlic\"],\n\"status\": \"cooking\"\n<<_CLOSE_}_>>\nIn the JSON example above, the keys are the words on the left: toppings,\ncrust, and status. They tell us what attributes the pizza order contains. The\nvalues are the parts to the right. These are the actual details of the order.\n\nFigure 1. JSON key and value.\nIf you read a line from left to right, you get a fairly natural English sentence.\nTaking the first line as an example, we could read it as, \"the crust for this\npizza is original style.\" The second line can also be read — in JSON, a value\nthat starts and ends with square brackets ([]) is a list of values. So, we read\nthe second line of the order as, \"the toppings for this order are: cheese,\npepperoni, and garlic.\"\nSometimes, you want to use an object as the value for a key. Let's extend our\npizza order with customer details so you can see what this might look like:\n<<_OPEN_{_>>\n\"crust\": \"original\",\n\n\"toppings\": [\"cheese\", \"pepperoni\", \"garlic\"],\n\"status\": \"cooking\",\n\"customer\": <<_OPEN_{_>>\n\"name\": \"Brian\",\n\"phone\": \"573-111-1111\"\n<<_CLOSE_}_>>\n<<_CLOSE_}_>>\nIn this updated version, we see that a new key, \"customer\", is added. The\nvalue for this key is another set of keys and values that provide details about\nthe customer that placed the order. Cool trick, huh?! This is called an\nAssociative Array. Don't let the technical term intimidate you though - an\nassociative array is just a nested object.\nXML\nXML has been around since 1996 1. With age, it has become a very mature\nand powerful data format. Like JSON, XML provides a few simple building\nblocks that API makers use to structure their data. The main block is called a\nnode.\nLet's see what our pizza order might look like in XML:\n<order>\n<crust>original</crust>\n\n<toppings>\n<topping>cheese</topping>\n<topping>pepperoni</topping>\n<topping>garlic</topping>\n</toppings>\n<status>cooking</status>\n</order>\nXML always starts with a root node, which in our pizza example is \"order.\"\nInside the order are more \"child\" nodes. The name of each node tells us the\nattribute of the order (like the key in JSON) and the data inside is the actual\ndetail (like the value in JSON).\n\nFigure 2. XML node and value.\nYou can also infer English sentences by reading XML. Looking at the line\nwith \"crust\", we could read, \"the crust for the pizza is original style.\" Notice\nhow in XML, every item in the list of toppings is wrapped by a node. You\ncan see how the XML format requires a lot more text to communicate than\nJSON does.\nHow Data Formats Are Used In HTTP\nNow that we've explored some available data formats, we need to know how\nto use them in HTTP. To do so, we will say hello again to one of the\nfundamentals of HTTP: headers. In Chapter 2, we learned that headers are a\nlist of information about a request or response. There is a header for saying\nwhat format the data is in: Content-Type.\n\nWhen the client sends the Content-Type header in a request, it is telling the\nserver that the data in the body of the request is formatted a particular way. If\nthe client wants to send the server JSON data, it will set the Content-Type to\n\"application/json.\" Upon receiving the request and seeing that Content-Type,\nthe server will first check if it understands that format, and, if so, it will know\nhow to read the data. Likewise, when the server sends the client a response, it\nwill also set the Content-Type to tell the client how to read the body of the\nresponse.\nSometimes, the client can only speak one data format. If the server sends\nback anything other than that format, the client will fail and throw an error.\nFortunately, a second HTTP header comes to the rescue. The client can set\nthe Accept header to tell the server what data formats it is able to accept. If\nthe client can only speak JSON, it can set the Accept header to\n\"application/json.\" The server will then send back its response in JSON. If the\nserver doesn't support the format the client requests, it can send back an error\nto the client to let it know the request is not going to work.\nWith these two headers, Content-Type and Accept, the client and server can\nwork with the data formats they understand and need to work properly.\n\nFigure 3. Data format headers.\nChapter 3 Recap\nIn this chapter, we learned that for two computers to communicate, they need\nto be able to understand the data format passed to them. We were introduced\nto 2 common data formats used by APIs, JSON and XML. We also learned\nthat the Content-Type HTTP header is a useful way to specify what data\nformat is being sent in a request and the Accept header specifies the\nrequested format for a response.\n\nThe key terms we learned were:\n• JSON: JavaScript Object Notation\n• Object: a thing or noun (person, pizza order...)\n• Key: an attribute about an object (color, toppings...)\n• Value: the value of an attribute (blue, pepperoni...)\n• Associative array: a nested object\n• XML: Extensible Markup Language\nHomework\nUse the form in our site for Chapter 3 to make the following list of requests\nand see what responses you are given.\nInstructions\n1 Send a request with: Content-Type header = \"application/json\", Accept\nheader = \"application/json\", and data format = \"XML\".\n2 Send a request with: Content-Type header = \"application/json\", Accept\nheader = \"application/json\", and data format = \"JSON\".\n3 Ok, now just try changing things around and seeing what happens! :)\nNext\nIn the next chapter, we find out how two computers can establish trust using\nAuthentication in order to pass along sensitive data, like customer details or\nprivate content.\nNotes:\n1."


I’m using it in the prompt with {{ $json.text }}. But it throws the following error:

Error: Single '}' in template.
    at Object.parseFString [as f-string] (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@huggingface+infer_gjsgfqvwxawgggzmox3fuda37i/node_modules/langchain/dist/prompts/template.cjs:41:19)
    at parseTemplate (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@huggingface+infer_gjsgfqvwxawgggzmox3fuda37i/node_modules/langchain/dist/prompts/template.cjs:73:99)
    at Function.fromTemplate (/usr/local/lib/node_modules/n8n/node_modules/.pnpm/[email protected]_@[email protected]_@[email protected]_@huggingface+infer_gjsgfqvwxawgggzmox3fuda37i/node_modules/langchain/dist/prompts/prompt.cjs:96:41)
    at createSimpleLLMChain (/usr/local/lib/node_modules/n8n/packages/@n8n/nodes-langchain/dist/nodes/chains/ChainLLM/ChainLlm.node.js:11:42)
    at getChain (/usr/local/lib/node_modules/n8n/packages/@n8n/nodes-langchain/dist/nodes/chains/ChainLLM/ChainLlm.node.js:20:16)
    at Object.execute (/usr/local/lib/node_modules/n8n/packages/@n8n/nodes-langchain/dist/nodes/chains/ChainLLM/ChainLlm.node.js:96:31)
    at Workflow.runNode (/usr/local/lib/node_modules/n8n/packages/workflow/dist/Workflow.js:673:19)
    at /usr/local/lib/node_modules/n8n/packages/core/dist/WorkflowExecute.js:652:53

I’ve even exited all curly braces with <<_OPEN_{_>> and <<_CLOSE_}_>> as you can see, to no avail. It also doesn’t work when I don’t use <<_OPEN_{_>> and <<_CLOSE_}_>>. I’ve tried with JSON.stringify also, it doesn’t work either.

Can anbody help me out or should I report on github? I run the docker beta

Looking at the example JSON you give, it looks like it is not valid JSON as there is one closing } missing.

To be able to help you, it would be best if you could create a workflow that reproduces the error you are seeing and then post it here. So create a basic version, pin the incoming data of the nodes, download it, and then paste the content of the JSON file here. We can then have a look and respond with a fixed version.

But generally, am I at least 100% sure that the {{ $json.text }} is not the problem. It must be the data it resolves to.

Yes the problem is the data, I know, but you should be able to send invalid json inside the text without bugging out no? And thx for the quick reply :slight_smile:

I would have assumed so to, but something in LangChain does not seem to like it.

I just looked at your workflow. Sadly does it not have any data pinned.

It says “This data is pinned” in the merge node, in the chain it isn’t possible because no output only input, doesn’t complete, will try to paste again in the previous post

You have to download the workflow (via the “Download” button behind the 3 dots), open it, and copy it from there. If you copy & paste directly, the pinned data will be lost.

Ohw sorry missed tha part :slight_smile:

Honestly, it is not very intuitive, and I am also always confused as to why the data is missing with a simple copy & paste. Just posted in the internal Engineering channel if that was really intended or if it is a bug.

Woohoo! Made it through the bugging output by replacing all curlies with double curlies! Thanks to this stackoverflow → f-string: single '}' is not allowed Python SPARQL Query problem - Stack Overflow. Thx for your help, mate

// Escape curly braces
function replace_braces(text) {
    return text.replace(/{/g, '{{').replace(/}/g, '}}');

// Loop over input items and add a new field called 'myNewField' to the JSON of each one
for (const item of $input.all()) { 
  item.json.text = replace_braces(item.json.text);

return $input.all();
1 Like

It’s great to hear that you found a solution. Have fun!

1 Like

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

@dRAT3 fyi the issue got now fixed properly by @oleg with this PR. The latest ai-beta image includes this fix.