Repository navigation
Keep memory runs and alerts alive when an LLM backend is unreachable - #289
Merged
Merged
Conversation
While ninfer-3090 was down after the 2026-11-05 farm reboot, Discovery
failed every job with result.error {UPSTREAM_ERROR, name resolution}.
The bot read only job.error, so every failure became the generic
"dialog job failed": it was not retryable, the breaker never opened, the
routing admin report stayed silent for 30 h, and each memory run spent
all five attempts within half an hour (7,897 runs retired).
- Decode Discovery's result.error and report it as "CODE: message".
UPSTREAM_ERROR, SERVICE_NOT_FOUND, SERVICE_DISABLED and
ENDPOINT_NOT_FOUND become AifarmClientError::BackendUnavailable,
classified as ProviderUnavailable like Transport.
- Release a memory run instead of failing it when extraction fails
because no LLM backend could take the call.
- Collapse a deferred memory pipeline to one followup job delayed by
the retry interval, so an outage is probed every 15 s instead of
spinning every worker on claims.
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.
Problem
From 2026-11-05 15:26 to 2026-11-06 21:58 UTC the GPU2 backend (
ninfer-3090) was not running. Discovery failed every job withresult.error = {code: "UPSTREAM_ERROR", message: "[Errno -3] Temporary failure in name resolution"}. The bot read only the top-leveljob.error, so:dialog job failed. It matched no retry rule, so the walker never charged the breaker, never emittedcircuit_open_exhaustion, and the owner's routing incident report stayed silent for 30 h. Before the reboot, while the same backend returnedconnection refused, that report had fired.memory_consolidationjobs per day.Change
result.erroris decoded (DiscoveryJobResult.error,DiscoveryJobStatus.error_code). A failed job now reportsCODE: message. The codes that mean the backend was never reached (UPSTREAM_ERROR,SERVICE_NOT_FOUND,SERVICE_DISABLED,ENDPOINT_NOT_FOUND) produce the newAifarmClientError::BackendUnavailable, whichretryable_reasonclassifies asProviderUnavailable, as it already does forTransport.UPSTREAM_TIMEOUTand unknown codes stayUpstream.ProviderUnavailable/CapacityUnavailable, or routingNoCandidates/Exhausted/RouteUnavailable/CapacityWaitTimeout), the run is released, as the embedder gate already does. Other extractor errors still fail the run.MEMORY_CONSOLIDATION_BACKEND_RETRY_INTERVAL(15 s, renamed from the embedder-only constant). The first productive probe ramps the pipeline back up through the existing amplification.circuit_open_exhaustion. A walker test pins this forBackendUnavailableand shows that the old generic error never reached the report.Verification
cargo fmt --allcargo clippy --workspace --all-targets -- -D warnings: passedcargo test -p openplotva-llm -p openplotva-app -p openplotva-taskman: 1,460 app + 225 llm + 68 taskman tests passaifarm: a real Discovery failed-job JSON decodes toUPSTREAM_ERROR: …; the four codes map toBackendUnavailable; timeout, internal and bare failures stayUpstream/dialog job failed.retry:BackendUnavailableisProviderUnavailablealthough its text matches no phrase rule.memory_runtime: classification table (unreachable, transport, 503 loading, capacity and routing errors release; timeout, generic, response and deadline errors and store failures do not); an unreachable backend releases the run without failing it; a timeout still spends the attempt; three deferring workers leave exactly one delayed probe job; the embedder deferral's followup is not dequeued before the retry interval.routed_attempts: sixBackendUnavailablefailures open the circuit and queue an aggregated admin report; six genericdialog job failedfailures do not.Operations already done (not part of this diff)
ninfer-3090was recreated on the farm at 21:58 UTC; memory extraction on GPU2 runs without errors.attempts = 0(status keptfailed, so they stay outsideMEMORY_MAX_QUEUED_RUNS) and are draining at ~14 runs/min.net.ipv4.ip_nonlocal_bind=1and a container watchdog that recreates compose services Docker failed to start. Installed on the farm.Compatibility
No schema, prompt, route or Redis change. Operator-visible error texts change from
dialog job failedto Discovery'sCODE: messagewhen Discovery provides one. Unreachable-backend failures become retryable for every routed workflow, so the walker falls back and charges breakers on them, as it already did forconnection refused.