Jinja template runtime validation error fix
Hi all,
Leaving here a quick fix just in case someone finds it useful.
The implemented chat templates break agentic tool usage in environments like Kilocode (and forks alike) and Openclaw where jinja breaks apart during unsupported role usage, triggering an exception error 500. Other chat templates also break the same, so it's no exclusive to Unsloth.
Produced Stack:
llama.cpp b7907
Devstral Small 2 Unsloth Q8_0 or LM Studio Q8_0
Error Trigger Examples
Kilocode context compaction
Kilocode subtask completion to Orchestrator
Kilocode randomly breaking mid-session
Openclaw unusable in any shape
Error output:
srv operator(): got exception: {"error":{"code":500,"message":"\n------------\nWhile executing CallExpression at line 12, column 27 in source:\n...assistant' %}↵ {{ raise_exception('Expected assistant role') }}↵ {%- e...\n \^\nError: Jinja Exception: Expected assistant role","type":"server_error"}}
srv log_server_r: done request: POST /v1/chat/completions [172.18.0.1](http://172.18.0.1) 500
The solution was to disable --jinja and create the alternative jinja template by adding your modified chat template adding exception for unsupported roles.
{{#- Unsloth template fixes #}
{%- set yesterday_day = strftime_now("%d") %}
{%- set yesterday_month = strftime_now("%m") %}
{%- set yesterday_year = strftime_now("%Y") %}
{%- set today_date = yesterday_year + '-' + yesterday_month + '-' + yesterday_day %}
{%- if yesterday_day == '01' %}
{#- Jinja doesnt allow minus 1 date - Unsloth alternative #}
{%- if yesterday_month == '01' %}
{%- set yesterday_day = '31' %}
{%- set yesterday_month = '12' %}
{%- if yesterday_year == '2024' %}
{%- set yesterday_year = '2023' %}
{%- elif yesterday_year == '2025' %}
{%- set yesterday_year = '2024' %}
{%- elif yesterday_year == '2026' %}
{%- set yesterday_year = '2025' %}
{%- elif yesterday_year == '2027' %}
{%- set yesterday_year = '2026' %}
{%- elif yesterday_year == '2028' %}
{%- set yesterday_year = '2027' %}
{%- elif yesterday_year == '2029' %}
{%- set yesterday_year = '2028' %}
{%- elif yesterday_year == '2030' %}
{%- set yesterday_year = '2029' %}
{%- elif yesterday_year == '2031' %}
{%- set yesterday_year = '2030' %}
{%- elif yesterday_year == '2032' %}
{%- set yesterday_year = '2031' %}
{%- elif yesterday_year == '1970' %}
{#- Stop llama_cpp from erroring out #}
{%- set yesterday_year = '1970' %}
{%- else %}
{{- raise_exception('Unsloth custom template does not support years > 2032. Error year = [' + yesterday_year + ']') }}
{%- endif %}
{%- elif yesterday_month == '02' %}
{%- set yesterday_day = '31' %}
{%- set yesterday_month = '01' %}
{%- elif yesterday_month == '03' %}
{%- set yesterday_month = '02' %}
{%- set yesterday_day = '28' %}
{%- if yesterday_year == '2024' %}
{%- set yesterday_day = '29' %}
{%- elif yesterday_year == '2028' %}
{%- set yesterday_day = '29' %}
{%- elif yesterday_year == '2032' %}
{%- set yesterday_day = '29' %}
{%- elif yesterday_year == '1970' %}
{#- Stop llama_cpp from erroring out #}
{%- set yesterday_day = '29' %}
{%- else %}
{{- raise_exception('Unsloth custom template does not support years > 2032. Error year = [' + yesterday_year + ']') }}
{%- endif %}
{%- elif yesterday_month == '04' %}
{%- set yesterday_day = '31' %}
{%- set yesterday_month = '03' %}
{%- elif yesterday_month == '05' %}
{%- set yesterday_day = '30' %}
{%- set yesterday_month = '04' %}
{%- elif yesterday_month == '06' %}
{%- set yesterday_day = '31' %}
{%- set yesterday_month = '05' %}
{%- elif yesterday_month == '07' %}
{%- set yesterday_day = '30' %}
{%- set yesterday_month = '06' %}
{%- elif yesterday_month == '08' %}
{%- set yesterday_day = '31' %}
{%- set yesterday_month = '07' %}
{%- elif yesterday_month == '09' %}
{%- set yesterday_day = '31' %}
{%- set yesterday_month = '08' %}
{%- elif yesterday_month == '10' %}
{%- set yesterday_day = '30' %}
{%- set yesterday_month = '09' %}
{%- elif yesterday_month == '11' %}
{%- set yesterday_day = '31' %}
{%- set yesterday_month = '10' %}
{%- elif yesterday_month == '12' %}
{%- set yesterday_day = '30' %}
{%- set yesterday_month = '11' %}
{%- endif %}
{%- elif yesterday_day == '02' %}
{%- set yesterday_day = '01' %}
{%- elif yesterday_day == '03' %}
{%- set yesterday_day = '02' %}
{%- elif yesterday_day == '04' %}
{%- set yesterday_day = '03' %}
{%- elif yesterday_day == '05' %}
{%- set yesterday_day = '04' %}
{%- elif yesterday_day == '06' %}
{%- set yesterday_day = '05' %}
{%- elif yesterday_day == '07' %}
{%- set yesterday_day = '06' %}
{%- elif yesterday_day == '08' %}
{%- set yesterday_day = '07' %}
{%- elif yesterday_day == '09' %}
{%- set yesterday_day = '08' %}
{%- elif yesterday_day == '10' %}
{%- set yesterday_day = '09' %}
{%- elif yesterday_day == '11' %}
{%- set yesterday_day = '10' %}
{%- elif yesterday_day == '12' %}
{%- set yesterday_day = '11' %}
{%- elif yesterday_day == '13' %}
{%- set yesterday_day = '12' %}
{%- elif yesterday_day == '14' %}
{%- set yesterday_day = '13' %}
{%- elif yesterday_day == '15' %}
{%- set yesterday_day = '14' %}
{%- elif yesterday_day == '16' %}
{%- set yesterday_day = '15' %}
{%- elif yesterday_day == '17' %}
{%- set yesterday_day = '16' %}
{%- elif yesterday_day == '18' %}
{%- set yesterday_day = '17' %}
{%- elif yesterday_day == '19' %}
{%- set yesterday_day = '18' %}
{%- elif yesterday_day == '20' %}
{%- set yesterday_day = '19' %}
{%- elif yesterday_day == '21' %}
{%- set yesterday_day = '20' %}
{%- elif yesterday_day == '22' %}
{%- set yesterday_day = '21' %}
{%- elif yesterday_day == '23' %}
{%- set yesterday_day = '22' %}
{%- elif yesterday_day == '24' %}
{%- set yesterday_day = '23' %}
{%- elif yesterday_day == '25' %}
{%- set yesterday_day = '24' %}
{%- elif yesterday_day == '26' %}
{%- set yesterday_day = '25' %}
{%- elif yesterday_day == '27' %}
{%- set yesterday_day = '26' %}
{%- elif yesterday_day == '28' %}
{%- set yesterday_day = '27' %}
{%- elif yesterday_day == '29' %}
{%- set yesterday_day = '28' %}
{%- elif yesterday_day == '30' %}
{%- set yesterday_day = '29' %}
{%- elif yesterday_day == '31' %}
{%- set yesterday_day = '30' %}
{%- endif %}
{#- Edits made by Unsloth #}
{%- set yesterday_date = yesterday_year + '-' + yesterday_month + '-' + yesterday_day %}
{#- Default system message if no system prompt is passed. #}
{%- set default_system_message = "You are Devstral-Small-2-24B-Instruct-2512, a Large Language Model (LLM) created by Mistral AI, a French startup headquartered in Paris.\nYou power an AI assistant called Le Chat.\nYour knowledge base was last updated on 2023-10-01.\nThe current date is " + today_date + ".\n\nWhen you\'re not sure about some information or when the user\'s request requires up-to-date or specific data, you must use the available tools to fetch the information. Do not hesitate to use tools whenever they can provide a more accurate or complete response. If no relevant tools are available, then clearly state that you don\'t have the information and avoid making up anything.\nIf the user\'s question is not clear, ambiguous, or does not provide enough context for you to accurately answer the question, you do not try to answer it right away and you rather ask the user to clarify their request (e.g. \"What are some good restaurants around me?\" => \"Where are you?\" or \"When is the next flight to Tokyo\" => \"Where do you travel from?\").\nYou are always very attentive to dates, in particular you try to resolve dates (e.g. \"yesterday\" is " + yesterday_date + ") and when asked about information at specific dates, you discard information that is at another date.\nYou follow these instructions in all languages, and always respond to the user in the language they use or request.\nNext sections describe the capabilities that you have.\n\n# WEB BROWSING INSTRUCTIONS\n\nYou cannot perform any web search or access internet to open URLs, links etc. If it seems like the user is expecting you to do so, you clarify the situation and ask the user to copy paste the text directly in the chat.\n\n# MULTI-MODAL INSTRUCTIONS\n\nYou have the ability to read images, but you cannot generate images. You also cannot transcribe audio files or videos.\nYou cannot read nor transcribe audio files or videos.\n\n# TOOL CALLING INSTRUCTIONS\n\nYou may have access to tools that you can use to fetch information or perform actions. You must use these tools in the following situations:\n\n1. When the request requires up-to-date information.\n2. When the request requires specific data that you do not have in your knowledge base.\n3. When the request involves actions that you cannot perform without tools.\n\nAlways prioritize using tools to provide the most accurate and helpful response. If tools are not available, inform the user that you cannot perform the requested action at the moment." %}
{#- Begin of sequence token. #}
{{- bos_token }}
{#- Handle system prompt if it exists. #}
{%- if messages[0]['role'] == 'system' %}
{{- '[SYSTEM_PROMPT]' -}}
{%- if messages[0]['content'] is string %}
{{- messages[0]['content'] -}}
{%- else %}
{%- for block in messages[0]['content'] %}
{%- if block['type'] == 'text' %}
{{- block['text'] }}
{%- else %}
{{- raise_exception('Only text chunks are supported in system message contents.') }}
{%- endif %}
{%- endfor %}
{%- endif %}
{{- '[/SYSTEM_PROMPT]' -}}
{%- set loop_messages = messages[1:] %}
{%- else %}
{%- set loop_messages = messages %}
{%- if default_system_message != '' %}
{{- '[SYSTEM_PROMPT]' + default_system_message + '[/SYSTEM_PROMPT]' }}
{%- endif %}
{%- endif %}
{#- Tools definition #}
{%- set tools_definition = '' %}
{%- set has_tools = false %}
{%- if tools is defined and tools is not none and tools|length > 0 %}
{%- set has_tools = true %}
{%- set tools_definition = '[AVAILABLE_TOOLS]' + (tools| tojson) + '[/AVAILABLE_TOOLS]' %}
{{- tools_definition }}
{%- endif %}
{#- Handle conversation messages. #}
{%- for message in loop_messages %}
{#- System messages #}
{%- if message['role'] == 'system' %}
{{- '[SYSTEM_PROMPT]' + message['content'] + '[/SYSTEM_PROMPT]' }}
{#- User messages support text content or text and image chunks. #}
{%- elif message['role'] == 'user' %}
{%- if message['content'] is string %}
{{- '[INST]' + message['content'] + '[/INST]' }}
{%- elif message['content'] | length > 0 %}
{{- '[INST]' }}
{%- if message['content'] | length == 2 %}
{%- set blocks = message['content'] | sort(attribute='type') %}
{%- else %}
{%- set blocks = message['content'] %}
{%- endif %}
{%- for block in blocks %}
{%- if block['type'] == 'text' %}
{{- block['text'] }}
{%- elif block['type'] in ['image', 'image_url'] %}
{{- '[IMG]' }}
{%- else %}
{{- raise_exception('Only text, image, and image_url chunks are supported in user message content.') }}
{%- endif %}
{%- endfor %}
{{- '[/INST]' }}
{%- else %}
{{- raise_exception('User message must have a string or a list of chunks in content.') }}
{%- endif %}
{#- Assistant messages support text content or text and image chunks. #}
{%- elif message['role'] == 'assistant' %}
{%- if (message['content'] is none or message['content'] == '' or message['content']|length == 0) and (message['tool_calls'] is not defined or message['tool_calls'] is none or message['tool_calls']|length == 0) %}
{{- raise_exception('Assistant message must have a string or a list of chunks in content or a list of tool calls.') }}
{%- endif %}
{%- if message['content'] is string %}
{{- message['content'] }}
{%- elif message['content'] is iterable and message['content'] | length > 0 %}
{%- for block in message['content'] %}
{%- if block['type'] == 'text' %}
{{- block['text'] }}
{%- else %}
{{- raise_exception('Only text chunks are supported in assistant message contents.') }}
{%- endif %}
{%- endfor %}
{%- endif %}
{%- if message['tool_calls'] is defined and message['tool_calls'] is not none and message['tool_calls']|length > 0 %}
{%- for tool in message['tool_calls'] %}
{%- set arguments = tool['function']['arguments'] %}
{%- if arguments is not string %}
{%- set arguments = arguments|tojson|safe %}
{%- elif arguments == '' %}
{%- set arguments = '{}' %}
{%- endif %}
{{- '[TOOL_CALLS]' + tool['function']['name'] + '[ARGS]' + arguments }}
{%- endfor %}
{%- endif %}
{#- End of sequence token for each assistant message. #}
{{- eos_token }}
{#- Tool messages only support text content. #}
{%- elif message['role'] == 'tool' %}
{{- '[TOOL_RESULTS]' + message['content']|string + '[/TOOL_RESULTS]' }}
{#- Raise exception for unsupported roles. #}
{%- else %}
{{- raise_exception('Only user, assistant, tool, and system roles are supported, got ' + message['role'] + '.') }}
{%- endif %}
{%- endfor %}
{#- Copyright 2025-present Unsloth. Apache 2.0 License. #}
Sorry let me investigate Devstral - we utilized Mistral's official one, and added the system prompt, so most likely Mistral's original one might be broken somewhere sadly
I ran into a jinja related error for Devstral. However, I believe it is due to the date being March 1, and yesterday being February 28.
Apologies if this isn't the right place to comment (a quick search brought me here before I temporarily resolved the issue by moving my system clock forward by a day).
I hope this helps!
render_message_to_json: Neither string content nor typed content is supported by the template. This is unexpected and may lead to issues.
srv init: init: chat template parsing error:
------------
While executing CallExpression at line 51, column 32 in source:
... else %}↵ {{- raise_exception('Unsloth custom template does not suppo...
^
Error: Jinja Exception: Unsloth custom template does not support years > 2032. Error year = [2026]
srv init: init: please consider disabling jinja via --no-jinja, or use a custom chat template via --chat-template
srv init: init: for example: --no-jinja --chat-template chatml
srv operator(): operator(): cleaning up before exit...
main: exiting due to model loading error
I ran into the same thing.
On https://huggingface.co/unsloth/Devstral-Small-2-24B-Instruct-2512-GGUF/discussions/9 there is a minimal template which can be used as a workaround: