unslothai/unsloth · warning · 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

Pydantic validation failure (HTTP 422) from the same chat_template_override validator: chat_template_byte_length(value) succeeded but the UTF-8 byte size exceeds MAX_CHAT_TEMPLATE_BYTES. The limit is on encoded bytes, not characters, so multi-byte text (Jinja with non-ASCII literals) hits it earlier than a character count suggests.

Source

Thrown at studio/backend/routes/settings.py:713

    gpu_ids: Optional[list[int]] = Field(default = None, max_length = MAX_GPU_IDS)
    # An all-default save carries no fields, like a forget; None keeps the legacy contract.
    remove: Optional[bool] = None
    # Fill in, don't replace: the backfill reads the map once then writes each model, so another
    # tab's save was overwritten by this browser's older copy. Field level, not entry level: a
    # legacy entry holds only some fields, and skipping it would strand the rest.
    fill_absent_fields: bool = False

    @field_validator("chat_template_override")
    @classmethod
    def _limit_chat_template_bytes(cls, value: Optional[str]) -> Optional[str]:
        # Mirrors LoadRequest.normalize_blank_chat_template_override.
        if value is None:
            return None
        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

    @field_validator(
        "max_seq_length",
        "custom_context_length",
        "spec_draft_n_max",
        "n_parallel",
        "n_batch",
        "n_ubatch",
        "gpu_layers",
        "n_cpu_moe",
        "gpu_ids",
        mode = "before",
    )
    @classmethod
    def _no_booleans(cls, value: Any) -> Any:
        # bool subclasses int and pydantic parses non-strictly, so `true` arrives as 1: a
        # payload could pin GPU 1 or set a one-token context. _bounded_int rejects bools but

View on GitHub (pinned to 203007d190)

Solutions

  1. Shrink the template: remove comments/blank lines, or override only the needed blocks.
  2. Compute the byte size with TextEncoder (JS) or len(s.encode('utf-8')) (Python) and stay under the limit before submitting.
  3. If you truly need a larger template, raise MAX_CHAT_TEMPLATE_BYTES at the source and redeploy — but that is a server constant, not a request parameter.

Example fix

# before
payload = {'chat_template_override': template}  # len(template.encode()) > limit -> 422

# after
MAX = 65536  # mirror of MAX_CHAT_TEMPLATE_BYTES
size = len(template.encode('utf-8'))
assert size <= MAX, f'{size} bytes exceeds {MAX}'
payload = {'chat_template_override': template}
Defensive patterns

Strategy: validation

Validate before calling

const bytes = new TextEncoder().encode(tpl).length;
if (bytes > MAX_CHAT_TEMPLATE_BYTES) {
  throw new Error(`Template is ${bytes} bytes, limit ${MAX_CHAT_TEMPLATE_BYTES}`);
}
await api.put(url, { chat_template_override: tpl });

Type guard

function templateWithinLimit(tpl: string, maxBytes: number): boolean {
  return new TextEncoder().encode(tpl).length <= maxBytes;
}

Try / catch

try { await api.put(url, { chat_template_override: tpl }); }
catch (e) {
  if (e.status === 422 && /exceeds/.test(e.detail?.toString() ?? '')) { compactTemplate(); return; }
  throw e;
}

Prevention

When it happens

Trigger: PUT the model-overrides payload with a chat template whose UTF-8 encoding exceeds the fixed byte cap — typically a large pasted Jinja template with whitespace or non-ASCII comments.

Common situations: Pasting the full template from a large model repo instead of only the differing part; templates with long HTML/whitespace; users counting characters instead of bytes.

Related errors


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