Skip to content

Chat template crash (Optional<Any> Jinja error) only triggers when tools are present — startup probe (#142) misses it #168

Description

@CodeAndCanvas728

Summary

chat_template.jinja in peculiar-ragdoll/Tiel-Coder-35B-A3B-MLX-oQ4e (the "Sharp chat template" from peculiar-ragdoll/Qwen-Sharp-Chat-Templates) throws Cannot convert value of type Optional<Any> to Jinja Value on any real agentic request that includes a tools array — but the model serves fine on --info / startup and answers plain (tool-less) requests correctly. The #142 startup probe doesn't catch this because it only renders a bare one-turn prompt with no tools, so the failure only surfaces at request time, in production, against real coding-agent clients (opencode, pi).

Repro

SwiftLM --model <path>/Tiel-Coder-35B-A3B-MLX-oQ4e --port 5413 --stream-experts --ssd-prefetch --prefill-size 2048 --ctx-size 32768 --max-tokens 4096
  • Plain request, no tools: works.

    curl http://127.0.0.1:5413/v1/chat/completions -d '{"model":"tiel","messages":[{"role":"user","content":"hi"}]}'
    → 200, coherent response
    
  • Real agentic client request (opencode run, pi --print), which includes a tools array in the payload: every attempt fails —

    AI_APICallError: The chat template shipped with .../tiel-oq4e is not valid Jinja and could not be
    parsed: runtime('Cannot convert value of type Optional<Any> to Jinja Value'). This is a defect in
    the model's chat_template.jinja (or the chat_template field of its tokenizer_config.json), not in
    the request — report it to whoever publishes the checkpoint. Pinning to an earlier revision of the
    model is the usual workaround.
    

What I ruled out

  • Not a recent regression. Pinned to the checkpoint's original template revision (commit 943cfc8, Sharp v22.3.2, before any tool-protocol-specific patches) — identical crash.
  • Not fixed by removing the template entirely to force the "simple text format" fallback (works for other checkpoints shipping no template at all, e.g. DeepSeek-V4-Flash) — with chat_template.jinja and the embedded tokenizer_config.json chat_template key both removed, the request instead hangs indefinitely (never reaches slot_launch in the server log) rather than crashing. Worse, not better.
  • Confirmed the startup probe passes cleanly — [SwiftLM] ✅ Ready — because it never exercises a tools-bearing turn.

Secondary finding: the opt-in heartbeat (#75) also breaks against real opencode

Enabling X-SwiftLM-Prefill-Progress: true does deliver the heartbeat payload, but opencode
1.18.30's strict client rejects it outright rather than skipping it:

AI_TypeValidationError: Type validation failed: Value: {"n_past":0,"status":"processing",
"n_prompt_tokens":1016,"fraction":0,"elapsed_seconds":2}.
Error message: [{"code":"invalid_union","errors":[[{"expected":"array","code":"invalid_type",
"path":["choices"],...}],[{"expected":"object","code":"invalid_type","path":["error"],...}]],...}]

#75's own e2e test only validates this against gemma-4-e4b-it-4bit with no tools involved —
it doesn't cover a model with a tools array in play, where a title-generation sub-call
(agent=title) hits this before the main turn even starts. Worth its own regression test
alongside a tools-bearing request.

Suggested fix

Extend the #142 startup probe to render one additional case with a minimal non-empty tools array (in addition to the existing bare one-turn prompt), so a checkpoint whose template only breaks under tool-calling fails fast at load time with the same clear MalformedChatTemplate diagnostic, instead of failing silently in production on the first real agentic request. Separately, add a tools-bearing request to #75's opencode e2e test so the heartbeat validation gap above gets caught too.

Environment

  • SwiftLM b711 (SwiftLM-b711-c70957c, macOS arm64)
  • Checkpoint: peculiar-ragdoll/Tiel-Coder-35B-A3B-MLX-oQ4e (qwen3_5_moe, Qwen35MoEModel, oQ4e quant)
  • Clients tested: opencode 1.18.30, pi 0.85.1 — both reproduce identically, ruling out a client-side cause

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions