Repository navigation
Conversation
MiniMax H3 defaults SageAttention on (server.js:8110), and the route gate refused with 409 h3_sage_attention_unavailable whenever probeSageAttention() reported ready !== true. That probe inspects a ComfyUI Python environment on *this* machine's filesystem. When ComfyUI runs in a container or on another host — a supported configuration, since the app talks to it over a URL — there is no local interpreter to inspect, so the gate refused every h3 render, including requests that never asked for SageAttention. The probe now distinguishes "never measured" from "measured and unusable": it reports verifiable: false on the no-interpreter path, and verifiable: true in publicProbe and in the catch branch where it had an interpreter and ran. A new h3SageAttentionDecision() reads that distinction. An unverifiable report degrades the render to standard attention instead of refusing it — ready stays false, so the job record is honest about which backend ran — while a missing KJNodes patch node and a probe that ran and found SageAttention broken still return exactly the same 409 as before. Unknown or absent report shapes fail safe and block. Verified: node --test goes 1134 -> 1144 (10 tests added, none removed), 0 failures, and the new tests are collected by the default invocation. The decision matrix was exercised with the real probe and the real report shape across five topologies, with a pre-fix negative control that still returns the original 409. Refs: BlackMixture#74
tmttodd
force-pushed
the
fix/remote-sage-attention-probe
branch
from
September 24, 2026 00:37
8c33cb3 to
188027a
Compare
This branch has not been deployed
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.
What this fixes
Fixes #74.
MiniMax H3 asks for SageAttention by default, and the route gate refused with 409
h3_sage_attention_unavailablewheneverprobeSageAttention()reportedready !== true. That probe inspects a ComfyUI Python environment on this machine's filesystem — but Mix Studio supports talking to a ComfyUI that runs in a container or on another host. There the check can never succeed, so every H3 render submitted with SageAttention is refused, including requests that never mention it.Root cause in one sentence: the gate treated "could not be inspected" as "inspected and unusable".
Reproduction on a live containerised engine
A controlled comparison: same engine, same tunnel, same scratch recipe, same prompt-free requests — with upstream
main(9bd99ad, this branch's own parent) on one side and this branch on the other. The fix's delta is the only variable.POST /api/animate(no prompt)main@9bd99ad{"engine":"h3","sageAttention":true}code=h3_sage_attention_unavailable(11.2 ms){"error":"Describe the motion first"}(17.9 ms){"engine":"h3"}— no attention field at all, the default path{"engine":"h3","sageAttention":false}Row 3 is the discriminator: with SageAttention off the request clears the gate and lands on ordinary prompt validation, so the 409 is the SageAttention gate rather than the missing prompt. The same pair measured against the released
v1.2.4gives the same 409 → 400, and there the 409 body's ownsageAttention.nodeReadyistrue— the server asserting that the patch node is present while refusing. On a fixed tree a prompt-bearing SageAttention request was deliberately not sent, since it would clear the gate and submit a real render.GET /api/metareports this, verbatim, on this branch:{"ready":false,"installable":false,"pythonReady":false,"verifiable":false, "reason":"Mix Studio has no local ComfyUI Python environment to inspect, so SageAttention cannot be verified on this machine. This is expected when ComfyUI runs on another host.", "packageReady":false,"nodeReady":true}On the baseline side — upstream
mainat9bd99ad— the same object reads"reason":"Choose the local ComfyUI folder so Mix Studio can verify its Python environment."and carries noverifiablefield at all, with the corroborating fields naming the blocked half ("missing": {"h3sage": []},"blockedBy":"sage-runtime") — the node half passing while the runtime half can never be checked.?refresh=1returns the identical object, so it is not a cached verdict.Nothing was queued on either side: the engine's
/queueand/historywere unchanged across every request (0 running / 0 pending; history 12 → 12 in both trees), which the sub-20 ms latencies already imply.The change
lib/sage-attention.js— the probe now separates "never measured" from "measured and unusable":verifiable: false, and no longer tells the user to choose a local ComfyUI folder, which cannot help when the engine is remote;publicProbeand the catch branch (interpreter present, probe ran, report unavailable) reportverifiable: true;h3SageAttentionDecision(sageRuntime, nodeReady), evaluatednodeReady → verifiable === false → ready === true, and defaulting to block for any absent or unknown shape.server.js— the gate consults the helper (:9706-9741). On an unverifiable report it rewrites the derived attention options as a pair through the same factory that built them (:9738) and re-reads the boolean from them (:9740), so the backend name and the boolean cannot disagree into the job record at:10234-10236.h3Attention/h3SageAttentionbecome assignable at:9505/:9511;h3SlaAttentionstaysconstand its gate at:9742-9758is untouched.What still refuses, unchanged
sageAttention: falsestandardsageattentionattentionBackend: "sla"selectedThe decision matrix was exercised end to end — the five topologies above plus the legacy
"sage"alias leg — against the real probe and the real report shape. A control run usingmain's ownlib/revision still returns the original 409 and the original message string, so the harness discriminates rather than agreeing with itself.Known limitation: this does not unblock the default H3 UI
h3sageremains in/api/meta'smissingComponents(that list keys offcapabilities.sageAttention?.ready !== trueatserver.js:1894, which staysfalse), so#generateBtnstill diverts into the setup dialog and never posts. The 409 was reachable by direct API callers — which is how we hit it — and the fix is aimed there. Making the UI path work means deciding how a remote engine should report verifiability, which is a larger question than this gate, so the badge semantics are deliberately untouched.Tests
node --teston the pinnedv1.2.4checkout: 1134 → 1144. Rebased on currentmain: 1327 → 1337, zero failures — delta exactly +10, with the new tests demonstrably collected by the default invocation (test/sage-attention-h3-gate.test.js, plus 3 intest/sage-attention.test.js). Verified under Node 22.23.2 (thequality.ymlmatrix version) as well as Node 26, with identical counts on both. The OS legs are yours to run — the Quality workflow on this PR is queued asaction_required, pending approval for a fork.CONTRIBUTING's three commands (
node --check server.js,node --check public/app.js,node --test) all pass; no dependency is added; no realdata/directory is touched (every run used a scratch data directory); and the decision logic lives in the focusedlib/module with its own tests, as the file prefers. A CHANGELOG entry is included under Unreleased.Out of scope, reported rather than fixed
lib/h3-sla-attention.js:155-162has the same shape — the un-actionable folder message on its no-local-interpreter path — and a remote engine that has the pinned SLA node would surface it, sinceserver.js:9745takes the!nodeReadybranch first and the node-absent case never reaches it. (Our own live SLA 409 is node-justified and does not demonstrate this; the correction in #74 records what it does and does not show.) Porting this fix there needs its own decision — degrade, or refuse with the platform reason that actually applies — so it is deliberately not in this PR.