unslothai/unsloth · error · ValueError

Chat template exceeds the {MAX_CHAT_TEMPLATE_BYTES}-byte lim

Error message

Chat template exceeds the {MAX_CHAT_TEMPLATE_BYTES}-byte limit.

What it means

Field validator on ValidateChatTemplateRequest.template enforcing a hard byte-size cap (MAX_CHAT_TEMPLATE_BYTES) on the chat template. The size is computed as the UTF-8 byte length (chat_template_byte_length), not character count, so templates with many multi-byte characters hit the limit sooner. Oversized templates are rejected because they bloat every tokenizer config request and can exceed downstream storage/transfer limits.

Source

Thrown at studio/backend/picker/schemas.py:37

    "reject": such a template can never render.
    """
    try:
        return len(value.encode("utf-8"))
    except UnicodeEncodeError:
        return None


class ValidateChatTemplateRequest(BaseModel):
    template: str = Field(default = "")

    @field_validator("template")
    @classmethod
    def _enforce_template_size(cls, value: str) -> str:
        size = chat_template_byte_length(value)
        if size is None:
            raise ValueError("Chat template contains unpaired surrogate characters.")
        if size > MAX_CHAT_TEMPLATE_BYTES:
            raise ValueError(f"Chat template exceeds the {MAX_CHAT_TEMPLATE_BYTES}-byte limit.")
        return value


class ValidateChatTemplateResponse(BaseModel):
    valid: bool
    error: Optional[str] = None


class ModelTemplateResponse(BaseModel):
    model_name: str
    chat_template: Optional[str] = None

View on GitHub (pinned to 203007d190)

Solutions

  1. Trim the template: move large few-shot examples or system text out of the template and pass them as message content at runtime instead.
  2. Reduce duplicated Jinja branches by using macros/loops over message roles.
  3. Verify the byte size locally before sending: len(template.encode('utf-8')) and keep it under the limit.

Example fix

# before
template = "{%- for shot in [LONG_FEW_SHOT_1, LONG_FEW_SHOT_2, ...] %}..."  # > limit bytes

# after
# keep only structural Jinja in the template; inject few-shot text via messages at inference time
template = "{%- for message in messages %}{{ message.content }}{% endfor %}"
Defensive patterns

Strategy: validation

Validate before calling

MAX_CHAT_TEMPLATE_BYTES = 65_536  # keep in sync with the server constant

def template_fits(template: str) -> bool:
    try:
        return len(template.encode("utf-8")) <= MAX_CHAT_TEMPLATE_BYTES
    except UnicodeEncodeError:
        return False  # unpaired surrogates — see separate error

Prevention

When it happens

Trigger: POSTing a ValidateChatTemplateRequest whose template's UTF-8 encoding exceeds MAX_CHAT_TEMPLATE_BYTES (e.g. a template with dozens of macro definitions or large embedded few-shot examples).

Common situations: Templates with long hardcoded system prompts or few-shot examples inlined; templates copied from another repo that include extensive branching for many message roles; non-ASCII (CJK/emoji) content roughly tripling byte count versus character count.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/bef6cfa934e98a37. Report an issue: GitHub.