Repository navigation
flm serve crashes when a request is missing a required field (POST {}) #755
Description
What happens
A request body that lacks a required field kills the flm serve process. No response is sent, and every later connection is refused until the server is restarted.
flm serve llama3.2:1b
curl -s -w '\nHTTP %{http_code}\n' http://127.0.0.1:52625/api/show \
-H 'Content-Type: application/json' -d '{}'
# curl exit 56, HTTP 000; the flm process is gone
curl -s http://127.0.0.1:52625/v1/models
# connection refusedWe saw the same crash with POST {} on /api/show, /api/generate and /v1/chat/completions, each tested in isolation. /api/chat and /v1/completions read their required field the same way, but we did not isolate them.
The same pattern explains a milder symptom. When /v1/embeddings gets no model, the handler happens to survive, and it answers HTTP 200 with {"error":"[json.exception.type_error.302] type must be string, but is invalid"}. The value it read was garbage, not a missing-key error.
Expected
A 400 naming the missing field, and the server keeps serving.
Cause
The handlers take const json& request and read required fields with operator[]:
handle_show:rest_handler.cpp:612request["model"]handle_generate::650request["prompt"]handle_chat::764request["messages"]handle_embeddings::882-889request["model"],request["input"]handle_openai_chat_completion::1103request["messages"]handle_openai_completion::1410request["prompt"]
On a const nlohmann::json, operator[] with a missing key is undefined behaviour. It is guarded only by JSON_ASSERT, which a release build compiles out, so it does not throw, and the surrounding try/catch never runs. The handler dereferences the map's end iterator instead.
Fix we are carrying
Check presence and type before each read, and refuse with a 400:
https://github.com/noamsto/nix-amd-ai/blob/46d7a73c1044435cec0ff08410e1a3bc87cbc544/pkgs/fastflowlm/patches/request-validation.patch
The require_field() helper is ported from OpenFlowLM-Next (src/server/openai_compat.hpp, Vegard Berget). Its error bodies carry an OpenAI-style string code ("missing_required_parameter"). Upstream send_response reads error.code with .get<int>() (server.cpp:736), which would throw on a string code. So the helper needs that line changed too. Our version of that change is in server-error-handling.patch in the same directory.
After the patch, all five endpoints answer POST {} with a 400 naming the field, and a normal chat request afterwards still completes. OpenFlowLM-Next's specs/server-api/tests/test_request_validation.py went from 0 of 22 passing to 14 passing with 8 skipped.
Environment
FLM v1.0.6 built from the tag, plus one downstream patch that only changes how send_response maps error.code to an HTTP status. That patch does not touch these read paths.
Ryzen AI MAX+ 395 (Strix Halo), XDNA2 NPU, 8 columns. NixOS, Linux 7.2.8, amdxdna 0.10, NPU FW 1.1.2.65. Model: llama3.2:1b.
We found this by running OpenFlowLM-Next's server-api conformance suite (specs/server-api/tests/, commit eb65600) against flm serve. Related but different trigger: #498.
Activity