fix(model): only announce a load at INFO when a load actually happens#11017
Merged
Conversation
backendLoader logged "BackendLoader starting" at INFO as its very first statement, unconditionally. That reads as "a model is being loaded", but backendLoader is not only a load path: in distributed mode Load() deliberately bypasses the local cache and calls backendLoader on every inference request so SmartRouter can re-pick a replica per request. The model is already resident, no process is spawned, and nothing is loaded, yet the banner fires at request rate. On a live cluster this produced ~5 "BackendLoader starting" lines per second for a single embedding model, sustained, starting 22 seconds after the load had already completed. The model was state=loaded with in_flight=0 and exactly one backend process on the worker. It looked exactly like a retry storm and cost real debugging time during an unrelated production investigation. The adjacent "effective runtime tuning" banner, documented as "logged once per load", had the same problem for the same reason. Emit both banners at INFO only when the model is not already resident, and keep the per-call trace at DEBUG for anyone following the routing path. isResident is a plain store lookup with no health probe and no eviction, so it is safe on the per-request hot path (unlike checkIsLoaded, which probes and can evict). Same class of defect as #10985: a log line that sends the reader after the wrong thing. Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Assisted-by: Claude Code:claude-opus-4-8[1m] [Read] [Edit] [Bash]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The observation
A live distributed LocalAI cluster logged
BackendLoader startingfor one embedding model roughly 5 times per second, sustained. It looks exactly like a retry storm.It is not. At the same moment:
state=loaded,in_flight=0The traffic was an agent pool issuing ordinary embedding requests against an already-resident model.
Root cause
backendLoaderis not only a load path. In distributed modeLoad()deliberately bypasses the local cache and callsbackendLoaderon every inference request, soSmartRoutercan re-pick a replica per request:That call lands in
loadModel's distributed branch, which routes to the existing replica and spawns nothing. ButbackendLoader's very first statement was an unconditionalxlog.Info("BackendLoader starting", ...), so the load banner fired at request rate for a model that was never being loaded.(In local mode
Load()early-returns onCheckIsLoadedbefore reachingbackendLoader, so the local path was never the source of these lines. The distributed per-request call is the real and intended behaviour — the routing is correct, only the logging was dishonest.)The adjacent
effective runtime tuningbanner, documented as "Logged once per load", had the same problem for the same reason: it was once per call, not once per load.The fix
Emit both banners at INFO only when the model is not already resident; keep the per-call trace at DEBUG for anyone following the routing path.
isResidentis a plain store lookup — no health probe, no eviction — so it is safe on the per-request hot path, unlikecheckIsLoaded, which probes over gRPC and can evict.An operator reading INFO logs can now tell a genuine cold model load from routine traffic against a resident model.
Why it matters
This log cost real debugging time: it caused an engineer to diagnose a non-existent retry storm during an unrelated production investigation. Same class of defect as #10985, which fixed
io.Copyerrors being labelledfailed to write filewhen they were read failures — a log line that sends the reader after the wrong thing.Tests
pkg/model/initializers_load_logging_test.go(Ginkgo/Gomega, internal package). Written first and confirmed red on behaviour:Logs are captured through a
sloghandler pinned atLevelInfo, so a wrong-severity emission fails the spec rather than passing silently. A third spec pins that a genuine cold load still announces at INFO, so the warm-path suppression cannot silence real loads.Verification
go build ./core/... ./pkg/...go test ./pkg/model/make lintRepo grepped (including
tests/e2e/) for anything pinning the log text: only a prose comment incore/services/nodes/router.gomentionsBackendLoaderlogs, no assertions.Scope is limited to load-related logging.