ollama: MLX structured output broken — libollama_xgrammar.dylib is never built (xgrammar is FetchContent'd at build time, no resource block)
brew config AND brew doctor output OR brew gist-logs <formula> link
brew doctorYour system is ready to brew.brew configHOMEBREW_VERSION: 6.0.21
ORIGIN: https://github.com/Homebrew/brew
HEAD: 560147012b9678b42ef5e83b690f0895552d1366
Branch: stable
HOMEBREW_PREFIX: /opt/homebrew
CPU: 18-core 64-bit arm_sotra
Clang: 21.0.0 build 2100
macOS: 26.6.2-arm64
CLT: 26.6.0.0.1781586589
Rosetta 2: falseVerification
- My
brew doctoroutput saysYour system is ready to brew.and am still able to reproduce my issue. - I ran
brew updateand am still able to reproduce my issue. - I have resolved all warnings from
brew doctorand that did not fix my problem. - I searched for recent similar issues and found no duplicates.
- My issue is not about a failure to build a formula from source.
- I did not use AI/LLM to create this issue, or I disclosed the tool and model used; I will answer maintainer questions myself without AI/LLM.
Disclosure: the investigation and the first draft of this report were produced with Claude (Anthropic). Every claim below was verified by running the commands shown. I will answer maintainer questions myself.
What were you trying to do (and why)?
Use Ollama's structured-output feature (format with a JSON schema) against an MLX-tagged model on Apple Silicon, so that a local model returns schema-conforming JSON instead of prose.
What happened (include all command output)?
The request fails with HTTP 501 on any MLX-tagged model, while the identical request succeeds on a GGUF model:
$ curl -s localhost:11434/api/generate -d '{
"model": "qwen3.6:27b-mlx",
"prompt": "Bench press 84 kg for 5, 5, 4.",
"stream": false,
"format": {"type":"object","properties":{"movement":{"type":"string"}},"required":["movement"]}
}'
{"error":"structured output is unavailable"}The server log gives the cause:
level=WARN source=grammar.go:75 msg="Structured output is unavailable"
error="xgrammar library not found at
/opt/homebrew/Cellar/ollama/0.33.2/libexec/lib/ollama/mlx_metal_v3/libollama_xgrammar.dylib:
no such file or directory"The file is absent:
$ find /opt/homebrew -name 'libollama_xgrammar*'
$ ls /opt/homebrew/Cellar/ollama/0.33.2/libexec/lib/ollama/mlx_metal_v3/
libmlxc.dylib libmlx.dylib mlx.metallibCause. Upstream builds xgrammar by fetching it over the network at build time — cmake/mlx/CMakeLists.txt:
FetchContent_Declare(xgrammar
GIT_REPOSITORY "https://github.com/mlc-ai/xgrammar.git"
GIT_TAG v0.2.5)Homebrew builds in a network-isolated sandbox, and the formula declares no resource for xgrammar the way it does for llama.cpp (Formula/o/ollama.rb). So the target is skipped and the dylib is never produced. grep -i xgrammar Formula/o/ollama.rb returns nothing at 0.33.2 or at current HEAD (0.33.3).
The official upstream build does ship it. Listing ollama-darwin.tgz for v0.33.3:
XGRAMMAR_LICENSE
XGRAMMAR_NOTICE
mlx_metal_v3/libmlxc.dylib
mlx_metal_v3/libollama_xgrammar.dylibSame relative path the WARN reports missing.
What did you expect to happen?
That format with a JSON schema would be honoured on MLX models, as it is on GGUF models and as it is with the official upstream darwin build.
Step-by-step reproduction instructions (by running brew commands)
brew update
brew install ollama
brew services start ollama # or: ollama serve
ollama pull qwen3.6:27b-mlx # any MLX-tagged model
curl -s localhost:11434/api/generate -d '{
"model": "qwen3.6:27b-mlx",
"prompt": "Bench press 84 kg for 5, 5, 4.",
"stream": false,
"format": {"type":"object","properties":{"movement":{"type":"string"}},"required":["movement"]}
}'
# -> {"error":"structured output is unavailable"}
find "$(brew --prefix)" -name 'libollama_xgrammar*'
# -> no outputReproduced on two Apple Silicon machines (M3 Max and M5 Max), both Homebrew ollama 0.33.2.
Source: Homebrew/homebrew-core