Skip to content

server: -md with an MTP assistant and no --spec-type yields a healthy server that 500s on every request #164

Description

@marksverdhei

Summary

Passing an MTP assistant model via -md without an explicit --spec-type draft-mtp does not fall back to plain generation. The server auto-selects draft-simple, which an MTP head model cannot satisfy. Startup completes, GET /health reports healthy, and then every completion request fails with HTTP 500.

A server that passes its health check and cannot serve a single request is the worst shape for this failure: behind a load balancer or an admission check it reads as available.

Reproduce

llama serve \
  -m gemma-4-12b-it-qat-q4_0.gguf \
  -md mtp-gemma-4-12B-it-Q4_0.gguf -ngld all \
  -c 4096 -ngl all -fa on --parallel 1 \
  --host 127.0.0.1 --port 8099 --no-webui --jinja

Note the absence of --spec-type draft-mtp.

curl -sf http://127.0.0.1:8099/health          # -> healthy
curl -s -o /dev/null -w '%{http_code}\n' \
     http://127.0.0.1:8099/v1/chat/completions \
     -H 'Content-Type: application/json' \
     -d '{"messages":[{"role":"user","content":"hi"}],"max_tokens":32}'

Actual

HTTP 500
{"error":{"code":500,"message":"decode() failed: failed to process speculative batch","type":"server_error"}}

Startup log:

W srv  load_model: [spec] failed to measure draft model memory: failed to create llama_context from model
I srv  load_model: loading draft model '.../mtp-gemma-4-12B-it-Q4_0.gguf'
W common_speculative_init: draft model is specified but 'draft' speculative type is not explicitly enabled - enabling it
I common_speculative_impl_draft_simple: adding speculative implementation 'draft-simple'
I common_speculative_impl_draft_simple: - n_max=3, n_min=0, p_min=0.000000

Adding --spec-type draft-mtp to the same command line makes the server work correctly (56.44 tok/s, 82.88% draft acceptance on this hardware).

Expected

One of:

  1. Fail at startup. failed to create llama_context from model is already detected during the draft memory measurement; treating it as fatal would turn a per-request 500 into a clear startup error.
  2. Refuse the auto-enable when the draft model is an MTP head that draft-simple cannot use, and say so.
  3. Fail the health check, so the server does not advertise itself as ready when no request can succeed.

Option 1 seems cheapest — the signal is already there and is currently logged at warning level.

Environment

  • build b9862-798cf6cbe
  • NVIDIA Quadro P5200 Mobile 16 GiB, compute capability 6.1, driver 580.159.04
  • Intel Core i7-7820HQ, Arch Linux
  • CMAKE_CUDA_ARCHITECTURES=61, GGML_CUDA_FORCE_MMQ=ON, GGML_CUDA_F16=OFF
  • target gemma-4-12b-it-qat-q4_0.gguf (93567e57a8fe10b2…), draft mtp-gemma-4-12B-it-Q4_0.gguf (b894e614824dfc27…)

Not checked on other backends or architectures; nothing here looks Pascal-specific, but I have only reproduced it on sm_61.

Artifacts

Repro script, the 500 response body, and the startup log are in #163 under docs/benchmarks/data/repro-2026-08-07/ (mtp-g2.sh, G2.1.json, G2.server.log.excerpt).

Acting agent: crystal-mom

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