Instructions to use froggeric/Qwen-Fixed-Chat-Templates with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use froggeric/Qwen-Fixed-Chat-Templates with MLX:
# Download the model from the Hub pip install huggingface_hub[hf_xet] huggingface-cli download --local-dir Qwen-Fixed-Chat-Templates froggeric/Qwen-Fixed-Chat-Templates
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
Model abrupt stop and thinking stop whenever tool calls contain unicode
The text of that exchange is here:
{"parentUuid":"fe4589da-bbe5-48b1-9061-acbb69af7ee5","isSidechain":false,"message":{"id":"chatcmpl-9tnIdC51SgdMk0LgqW8L2GRlIeUdkOPe","type":"message","role":"assistant","content":[{"type":"thinking","thinking":"OK, now I see the injection flow. Let me now look at what needs to change:\n\n1. The Frida gadget has SizeOfOptionalHeader = 0 — but the optional header IS there (we found PE32+ magic). However, the standard PE parsing uses IMAGE_NT_HEADERS* which includes the optional header size from the file header. With opt_size=0, nt->OptionalHeader.SizeOfImage and all other fields would be garbage or zero.\n\nWait, but our Python analysis showed:\n- SizeOfOptionalHeader (declared): 0\n\n\n- But PE32+ magic exists at offset 0x158 (which is e_lfanew + 24 + 4)\n\nSo the Frida modulator set SizeOfOptionalHeader to 0, effectively hiding the optional header from standard PE parsers. But the data is still there. This means the injector's nt->OptionalHeader.SizeOfImage, nt->OptionalHeader.AddressOfEntryPoint, and nt->OptionalHeader.DataDirectory all read from the WRONG offset since the parser thinks there's no optional header at e_lfanew + 24, which is actually where the optional header data begins.\n\nThe NT_HEADERS structure has the optional header immediately after the file header at offset +20, but with SizeOfOptionalHeader declared as 0, the sections should start at e_lfanew + 44 instead of at the actual optional header location.\n\nBut wait — I found PE32+ magic (0x20B) at offset 0x158, which is exactly where the optional header should begin if NT_HEADERS starts at 0x130. So the optional header is actually there and valid, even though SizeOfOptionalHeader claims to be 0. The injector's PE parsing must be reading past this field and using the actual optional header data anyway.\n\nLet me trace through what the Python scanner found: machine type is x64, there are 6 sections, and while SizeOfOptionalHeader reads as 0, it detected the PE32+ magic at offset 0x158 — which means the optional header is definitely present and being used despite the misleading size field. I'm realizing my struct format was wrong—I was packing NumberOfSections, TimeDateStamp, PointerToSymbolTable, and NumberOfSymbols together as <HHII, but that's actually four fields totaling 12 bytes when NumberOfSections is just 2 bytes. Let me recalculate the actual layout of IMAGE_FILE_HEADER to see where each field really falls.\n","signature":""}],"model":"YourMom","stop_reason":null,"stop_sequence":null,"usage":{"cache_read_input_tokens":157675,"input_tokens":1871,"output_tokens":0}},"type":"assistant","uuid":"c726748b-0049-4228-a67a-58c387b77680","timestamp":"2026-05-18T19:05:22.983Z","userType":"external","entrypoint":"cli","cwd":"D:\LocalMCP\frida","sessionId":"582dd9ba-f8cf-4497-a0e5-dc9e01b04702","version":"2.1.87","gitBranch":"main","slug":"abundant-brewing-sky"}
{"parentUuid":"c726748b-0049-4228-a67a-58c387b77680","isSidechain":false,"message":{"id":"chatcmpl-9tnIdC51SgdMk0LgqW8L2GRlIeUdkOPe","type":"message","role":"assistant","content":[{"type":"tool_use","id":"gSQ8lAH8olGYI1oew9cnSVVxKV2HH3le","name":"Bash","input":{"command":"D:/MiniConDo/envs/gpt/python.exe << 'PYEOF'\nimport struct, sys\nsys.stdout.reconfigure(encoding='utf-8')\n\npath = r'D:\LocalMCP\frida\build\subprojects\frida-core\lib\gadget\frida-gadget.dll'\nwith open(path, 'rb') as f:\n data = f.read(4096)\n\ne_lfanew = struct.unpack_from('<I', data, 0x3C)[0]\n\n# Byte-by-byte at the critical area\nprint(f"=== NT_HEADERS at 0x{e_lfanew:X} ===")\nfor i in range(e_lfanew, e_lfanew + 48):\n b = data[i]\n labels = {\n e_lfanew: "PE\\x00\\x00",\n e_lfanew+4: "Machine",\n e_lfanew+6: "NumSections",\n e_lfanew+8: "TimeDateStamp",\n e_lfanew+12: "PtrSymbolTable",\n e_lfanew+16: "NumSymbols",\n e_lfanew+18: "SizeOfOptionalHeader",\n e_lfanew+20: "Magic (PE32+)",\n }\n label = labels.get(i, "")\n print(f" [0x{i:04X}] 0x{b:02X} ({b:3d}){' ← '+label if label else ''}")\n\n# Parse with correct offsets\nmachine = struct.unpack_from('<H', data, e_lfanew+4)[0]\nnum_sec = struct.unpack_from('<H', data, e_lfanew+6)[0]\nopt_size = struct.unpack_from('<H', data, e_lfanew+18)[0]\nmagic = struct.unpack_from('<H', data, e_lfanew+20)[0]\n\nprint(f"\nParsed: Machine=0x{machine:04X}, Sections={num_sec}, OptSize={opt_size}")\nprint(f" Raw bytes at +16..+22:")\nfor i in range(e_lfanew+16, e_lfanew+22):\n print(f" [0x{i:04X}] = 0x{data[i]:02X}")\n\n# Check if SizeOfOptionalHeader is really 0\nprint(f"\nSizeOfOptionalHeader field value: {opt_size}")\nif opt_size == 0 and magic != 0x20B:\n # Maybe the optional header starts at a different offset?\n # Look for PE32+ magic in the range\n for off in range(e_lfanew+16, e_lfanew+32):\n m = struct.unpack_from('<H', data, off)[0]\n if m == 0x20B:\n print(f" *** Found PE32+ magic at 0x{off:X} (e_lfanew + {off-e_lfanew}) ***")\n break\nPYEOF\n","description":"Byte-by-byte NT_HEADERS inspection for SizeOfOptionalHeader"}}],"model":"YourMom","stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":1871,"cache_creation_input_tokens":0,"cache_read_input_tokens":157675,"output_tokens":1276,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"inference_geo":"","iterations":[],"speed":"standard"}},"type":"assistant","uuid":"6eb3e850-4652-49e7-89a7-18446f1d4512","timestamp":"2026-05-18T19:05:22.984Z","userType":"external","entrypoint":"cli","cwd":"D:\LocalMCP\frida","sessionId":"582dd9ba-f8cf-4497-a0e5-dc9e01b04702","version":"2.1.87","gitBranch":"main","slug":"abundant-brewing-sky"}
{"parentUuid":"6eb3e850-4652-49e7-89a7-18446f1d4512","isSidechain":false,"promptId":"07230ded-b778-4c92-873f-67ec7f57eafc","type":"user","message":{"role":"user","content":[{"tool_use_id":"gSQ8lAH8olGYI1oew9cnSVVxKV2HH3le","type":"tool_result","content":"=== NT_HEADERS at 0x140 ===\r\n [0x0140] 0x50 ( 80) ← PE\u0000\u0000\r\n [0x0141] 0x45 ( 69)\r\n [0x0142] 0x00 ( 0)\r\n [0x0143] 0x00 ( 0)\r\n [0x0144] 0x64 (100) ← Machine\r\n [0x0145] 0x86 (134)\r\n [0x0146] 0x06 ( 6) ← NumSections\r\n [0x0147] 0x00 ( 0)\r\n [0x0148] 0x40 ( 64) ← TimeDateStamp\r\n [0x0149] 0x61 ( 97)\r\n [0x014A] 0x0B ( 11)\r\n [0x014B] 0x6A (106)\r\n [0x014C] 0x00 ( 0) ← PtrSymbolTable\r\n [0x014D] 0x00 ( 0)\r\n [0x014E] 0x00 ( 0)\r\n [0x014F] 0x00 ( 0)\r\n [0x0150] 0x00 ( 0) ← NumSymbols\r\n [0x0151] 0x00 ( 0)\r\n [0x0152] 0x00 ( 0) ← SizeOfOptionalHeader\r\n [0x0153] 0x00 ( 0)\r\n [0x0154] 0xF0 (240) ← Magic (PE32+)\r\n [0x0155] 0x00 ( 0)\r\n [0x0156] 0x22 ( 34)\r\n [0x0157] 0x20 ( 32)\r\n [0x0158] 0x0B ( 11)\r\n [0x0159] 0x02 ( 2)\r\n [0x015A] 0x0E ( 14)\r\n [0x015B] 0x2C ( 44)\r\n [0x015C] 0x00 ( 0)\r\n [0x015D] 0x4C ( 76)\r\n [0x015E] 0x05 ( 5)\r\n [0x015F] 0x01 ( 1)\r\n [0x0160] 0x00 ( 0)\r\n [0x0161] 0x86 (134)\r\n [0x0162] 0x67 (103)\r\n [0x0163] 0x00 ( 0)\r\n [0x0164] 0x00 ( 0)\r\n [0x0165] 0x00 ( 0)\r\n [0x0166] 0x00 ( 0)\r\n [0x0167] 0x00 ( 0)\r\n [0x0168] 0xE8 (232)\r\n [0x0169] 0x94 (148)\r\n [0x016A] 0xFB (251)\r\n [0x016B] 0x00 ( 0)\r\n [0x016C] 0x00 ( 0)\r\n [0x016D] 0x10 ( 16)\r\n [0x016E] 0x00 ( 0)\r\n [0x016F] 0x00 ( 0)\r\n\r\nParsed: Machine=0x8664, Sections=6, OptSize=0\r\n Raw bytes at +16..+22:\r\n [0x0150] = 0x00\r\n [0x0151] = 0x00\r\n [0x0152] = 0x00\r\n [0x0153] = 0x00\r\n [0x0154] = 0xF0\r\n [0x0155] = 0x00\r\n\r\nSizeOfOptionalHeader field value: 0\r\n *** Found PE32+ magic at 0x158 (e_lfanew + 24) ***","is_error":false}]},"uuid":"1b56df2c-0ee5-49f9-9024-219321d6847e","timestamp":"2026-05-18T19:05:23.235Z","toolUseResult":{"stdout":"=== NT_HEADERS at 0x140 ===\r\n [0x0140] 0x50 ( 80) ← PE\u0000\u0000\r\n [0x0141] 0x45 ( 69)\r\n [0x0142] 0x00 ( 0)\r\n [0x0143] 0x00 ( 0)\r\n [0x0144] 0x64 (100) ← Machine\r\n [0x0145] 0x86 (134)\r\n [0x0146] 0x06 ( 6) ← NumSections\r\n [0x0147] 0x00 ( 0)\r\n [0x0148] 0x40 ( 64) ← TimeDateStamp\r\n [0x0149] 0x61 ( 97)\r\n [0x014A] 0x0B ( 11)\r\n [0x014B] 0x6A (106)\r\n [0x014C] 0x00 ( 0) ← PtrSymbolTable\r\n [0x014D] 0x00 ( 0)\r\n [0x014E] 0x00 ( 0)\r\n [0x014F] 0x00 ( 0)\r\n [0x0150] 0x00 ( 0) ← NumSymbols\r\n [0x0151] 0x00 ( 0)\r\n [0x0152] 0x00 ( 0) ← SizeOfOptionalHeader\r\n [0x0153] 0x00 ( 0)\r\n [0x0154] 0xF0 (240) ← Magic (PE32+)\r\n [0x0155] 0x00 ( 0)\r\n [0x0156] 0x22 ( 34)\r\n [0x0157] 0x20 ( 32)\r\n [0x0158] 0x0B ( 11)\r\n [0x0159] 0x02 ( 2)\r\n [0x015A] 0x0E ( 14)\r\n [0x015B] 0x2C ( 44)\r\n [0x015C] 0x00 ( 0)\r\n [0x015D] 0x4C ( 76)\r\n [0x015E] 0x05 ( 5)\r\n [0x015F] 0x01 ( 1)\r\n [0x0160] 0x00 ( 0)\r\n [0x0161] 0x86 (134)\r\n [0x0162] 0x67 (103)\r\n [0x0163] 0x00 ( 0)\r\n [0x0164] 0x00 ( 0)\r\n [0x0165] 0x00 ( 0)\r\n [0x0166] 0x00 ( 0)\r\n [0x0167] 0x00 ( 0)\r\n [0x0168] 0xE8 (232)\r\n [0x0169] 0x94 (148)\r\n [0x016A] 0xFB (251)\r\n [0x016B] 0x00 ( 0)\r\n [0x016C] 0x00 ( 0)\r\n [0x016D] 0x10 ( 16)\r\n [0x016E] 0x00 ( 0)\r\n [0x016F] 0x00 ( 0)\r\n\r\nParsed: Machine=0x8664, Sections=6, OptSize=0\r\n Raw bytes at +16..+22:\r\n [0x0150] = 0x00\r\n [0x0151] = 0x00\r\n [0x0152] = 0x00\r\n [0x0153] = 0x00\r\n [0x0154] = 0xF0\r\n [0x0155] = 0x00\r\n\r\nSizeOfOptionalHeader field value: 0\r\n *** Found PE32+ magic at 0x158 (e_lfanew + 24) ***","stderr":"","interrupted":false,"isImage":false,"noOutputExpected":false},"sourceToolAssistantUUID":"6eb3e850-4652-49e7-89a7-18446f1d4512","userType":"external","entrypoint":"cli","cwd":"D:\LocalMCP\frida","sessionId":"582dd9ba-f8cf-4497-a0e5-dc9e01b04702","version":"2.1.87","gitBranch":"main","slug":"abundant-brewing-sky"}
{"parentUuid":"1b56df2c-0ee5-49f9-9024-219321d6847e","isSidechain":false,"message":{"id":"chatcmpl-o3KpzM94LyGwfyqJhZg9kHr5PHjGjEi3","type":"message","role":"assistant","content":[{"type":"thinking","thinking":"\0\0\n","signature":""}],"model":"YourMom","stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":40,"cache_creation_input_tokens":0,"cache_read_input_tokens":160821,"output_tokens":6,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"inference_geo":"","iterations":[],"speed":"standard"}},"type":"assistant","uuid":"65c1f234-973e-416c-8509-3a7ed0ed16c4","timestamp":"2026-05-18T19:05:24.968Z","userType":"external","entrypoint":"cli","cwd":"D:\LocalMCP\frida","sessionId":"582dd9ba-f8cf-4497-a0e5-dc9e01b04702","version":"2.1.87","gitBranch":"main","slug":"abundant-brewing-sky"}
{"parentUuid":"65c1f234-973e-416c-8509-3a7ed0ed16c4","isSidechain":false,"type":"system","subtype":"turn_duration","durationMs":311782,"messageCount":365,"timestamp":"2026-05-18T19:05:24.969Z","uuid":"18b77a5b-9c32-40e4-9382-0467985660e4","isMeta":false,"userType":"external","entrypoint":"cli","cwd":"D:\LocalMCP\frida","sessionId":"582dd9ba-f8cf-4497-a0e5-dc9e01b04702","version":"2.1.87","gitBranch":"main","slug":"abundant-brewing-sky"}
{"parentUuid":"18b77a5b-9c32-40e4-9382-0467985660e4","isSidechain":false,"promptId":"2c6d2e36-c4f5-4ff5-998e-13baa003c980","type":"user","message":{"role":"user","content":"xontinue you stoped"},"uuid":"b9de37cc-dbcf-4764-879c-d04e82964a4a","timestamp":"2026-05-18T19:06:10.750Z","permissionMode":"bypassPermissions","userType":"external","entrypoint":"cli","cwd":"D:\LocalMCP\frida","sessionId":"582dd9ba-f8cf-4497-a0e5-dc9e01b04702","version":"2.1.87","gitBranch":"main","slug":"abundant-brewing-sky"}
{"type":"file-history-snapshot","messageId":"b9de37cc-dbcf-4764-879c-d04e82964a4a","snapshot":{"messageId":"b9de37cc-dbcf-4764-879c-d04e82964a4a","trackedFileBackups":{"build\frida-windows-x86-mt.txt":{"backupFileName":null,"version":5,"backupTime":"2026-05-18T19:06:10.754Z"},"build\frida-windows-x64-mt.txt":{"backupFileName":null,"version":5,"backupTime":"2026-05-18T19:06:10.754Z"},"releng\frida_version.py":{"backupFileName":"d77bed66334fef21@v2","version":2,"backupTime":"2026-05-18T18:44:17.768Z"},"configure-x64.bat":{"backupFileName":"c6e0ca336fd47d02@v2","version":2,"backupTime":"2026-05-18T18:44:17.768Z"}},"timestamp":"2026-05-18T19:06:10.792Z"},"isSnapshotUpdate":false}
{"parentUuid":"b9de37cc-dbcf-4764-879c-d04e82964a4a","isSidechain":false,"message":{"id":"chatcmpl-fgQFJTE6eWgI7MMUkq2EvQ4fPk67q4cn","type":"message","role":"assistant","content":[{"type":"thinking","thinking":"\0\0\n","signature":""}],"model":"YourMom","stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":40,"cache_creation_input_tokens":0,"cache_read_input_tokens":160821,"output_tokens":6,"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":0,"ephemeral_5m_input_tokens":0},"inference_geo":"","iterations":[],"speed":"standard"}},"type":"assistant","uuid":"040fee2a-a8f3-41c3-87f3-de4678b82284","timestamp":"2026-05-18T19:06:12.553Z","userType":"external","entrypoint":"cli","cwd":"D:\LocalMCP\frida","sessionId":"582dd9ba-f8cf-4497-a0e5-dc9e01b04702","version":"2.1.87","gitBranch":"main","slug":"abundant-brewing-sky"}
Hi @ManyOtherFunctions
I did a complete rebuild of the chat template from the ground up. Taken into account massive preresearch of common tool bugs and the nature of the Qwen3.5/Qwen3.6 itself.
I also ran a test against your specific case here, mine is green while this here is bugged.
Stay tuned, im releasing it this evening, just thinking about a good repo name und maybe another username.
Hi @ManyOtherFunctions
I did a complete rebuild of the chat template from the ground up. Taken into account massive preresearch of common tool bugs and the nature of the Qwen3.5/Qwen3.6 itself.I also ran a test against your specific case here, mine is green while this here is bugged.
Stay tuned, im releasing it this evening, just thinking about a good repo name und maybe another username.
wow! looking forward!
I uploaded v1.0 here:
https://huggingface.co/StableQuant/Qwen-Templates-Rebuild-Project/
Please test and report any errors to me.
v1.1 will be released soon (I think tomorrow), which includes more testcases etc. and dev role fixes etc. but so far, I have every common parsing error ruled out (17 common errors in Qwen3.5 chat templates are taken into account) and prework for v1.1 is nearly done.
There will be also a v1.2 release when I runned tests against the parsing and tool calling mechanism of the top 100 most common AI tools. But this will take a week or so.
So far, coded perfectly today for me in OpenHands. Rockstable for hours of testing.
short update: v1.1.2 is relased with additional fixes, like in v1.0, every parsing error like Unicode Characters and triple Quotes are handled by another logic there.
Sorry for the thread hijacking btw xD
Please test it out, I would consider it the first stable release
This happens because raw null bytes (\u0000) in tool outputs (like binary PE headers) truncate the prompt string inside C++ backends like llama.cpp. The template can't fix this directly, the harness needs to sanitize or strip null bytes in before returning tool outputs to the model. I'll close this thread for now.

