# LocalAI v4.9.0 — Release & Upgrade Intelligence
- **Product:** LocalAI (https://localai.io)
- **Version:** v4.9.0
- **Released:** Aug 20, 2026
- **Impact Score:** 7/10
- **Breaking Changes:** Source flagged
- **Canonical Analysis:** https://changelogs.us/localai/updates/v4.9.0/

## Executive Summary (TL;DR)
LocalAI v4.9.0. Source highlight: 🎉 LocalAI 4.9.0 Release! 🚀

## Breaking Changes & Deprecations
- Breaking Changes 🛠 * fix(auth): protect HTTP routes by default by @localai-bot in https://github.com/mudler/LocalAI/pull/11602 ### Bug fixes :bug:

## New Features
- **Metal is actually on in two macOS backends.** `stablediffusion-ggml` gated its Metal flags on an `OS=Darwin` variable the runner never defines, so the Darwin workflow's `BUILD_TYPE=metal` produced a build without `GGML_METAL_EMBED_LIBRARY=ON`, shipping a runtime source path that failed to expose `kernel_mul_mv_ext_bf16_f32_r1_5`. `parakeet-cpp` never forwarded `BUILD_TYPE=metal` to `PARAKEET_GGML_METAL` at all: on an M1 Air the same five-minute sample went from 82.57s to 50.18s with byte-ident
- **MCP servers stay visible when they fail.** Model-level MCP servers disappeared from Chat whenever connection setup or tool discovery failed, hiding container DNS, routing and VPN reachability problems. They now stay listed as disabled error rows with a per-server error, discovery retries while safely closing partially created sessions, and the model editor documents the expected `mcp.remote` and `mcp.stdio` formats.
- **Checksum mismatches retry.** A post-download SHA mismatch is now treated as a transient transfer failure: LocalAI removes the mismatched partial and lets the bounded planner retry a stale or corrupted CDN response, while still refusing unverified bytes. Direct `URI.DownloadFile` callers still see the mismatch immediately.
- **Audio transform rejects the wrong contract.** The audio-transform WebSocket accepted `realtime_audio` models and opened the frame-based `AudioTransformStream` RPC, which failed after the handshake with `NotImplementedError` for any-to-any models like `liquid-audio`. The use case is now validated before the backend loads, and any-to-any callers are pointed at the OpenAI Realtime API.
- **Invalid preload JSON names itself.** `PRELOAD_MODELS` / `--preload-models` now identifies which input was invalid and rejects non-array top-level values (including booleans and `null`) with the expected shape in the error.
- feat(modelartifacts): support bounded parallel Hugging Face file downloads

## Bug Fixes
- **Backend crashes say why.** An unexpected runtime exit logged its stderr only at debug level, so at default log level operators saw an exit code and nothing else. The final non-empty stderr line now rides the unexpected-exit warning, and a failed gRPC readiness preserves the process exit code plus the last stderr diagnostic bounded to 4 KiB.
- `fix(auth)`: protect HTTP routes by default - #11602
- `fix(distributed)`: run cold model loads as durable jobs instead of holding the advisory lock - #11514
- `fix(vllm-cpp)`: build every CUDA architecture the platform can host - #11512
- `fix(realtime)`: keep the ICE interface allow-list working with a fixed UDP port - #11466
- `fix(stablediffusion)`: embed Metal library - #11531
