Skip to content

apr run --gpu on qwen3moe Q4_K_M silently falls back to CPU (rc 14) instead of refusing by name — 0.69.1 must DECLARE it does not support qwen3moe on CUDA #3817

Closed

Description

@noahgift

Under epic #3710 and the operator's all-Q4_K-on-CUDA rule. This row exists because #3714 (the qwen3moe CUDA path) is moving to 0.70.0, and a release that does not support a model must SAY SO rather than quietly run it slowly.

The defect

apr run --gpu on a qwen3moe Q4_K_M file (Qwen3-30B-A3B-Instruct-2507, Qwen3-Coder-30B-A3B-Instruct) does not refuse. It returns rc 14 — "gpu was forced and selected, but its runtime attempt on this model failed and the generation ran on CPU" — and produces a CPU generation. Measured on lambda (RTX 4090), apr 0.69.0 (225b2a9ab) --features cuda, recorded on #3714: -v shows Architecture: Transformer [GGUF: qwen3moe] (48 layers) and no CUDA backend line before the refusal. apr qa gives rc 5 with no gates in the JSON — capability_match and golden_output both absent.

A user who passes --gpu and gets a silent CPU run at a fraction of the throughput they asked for has been told the wrong thing about their own hardware. This is the failure mode #3712 was filed to kill: the train can publish with "most models working" because absence reads as conformance.

It also fails the gate on its own terms. contracts/release-readiness-v1.yaml (#3715, landing with batch-1 / PR #3772) is explicit — a fallback receipt fails the gate naming the cell, exactly like a skip or an error:

a skipped, errored, fallback or stale receipt fails the gate naming the cell

Why a refusal and not a waiver or a RefusalCell

Both of the obvious escapes are closed, and closing them was deliberate:

  • Waivers are gone. release-readiness-v1.yaml: NO WAIVERS. EPIC: release train 0.69.1 — every capability ORACLE-PROVEN (CRUX cells) on gx10 and lambda; no defer #3710 originally permitted "a FAIL for the release unless the operator waives that cell by name"; that was removed. The standing operator ruling on contract exemptions (2026-08-21) points the same way.
  • A release:RefusalCell is not available for "unimplemented." The shape admits a refusal only where the model does not FIT, and requires both release:verdict in [refused] and release:arithmeticNamed in [true]. Qwen3-30B-A3B at Q4_K_M is roughly 18 GB against the 4090's 24 GB, and gx10's unified memory fits it outright, so citing memory arithmetic to mean "we did not build the path" would be a false arithmetic claim — worse than an honest failure. (The LONG rungs at the declared 262144 context legitimately do not fit lambda, and those remain genuine RefusalCells. That is a subset, not this row.)

So the honest shape is: 0.69.1 does not claim qwen3moe, the inventory says so, and the binary says so at load, by name.

## done_when

Notes for whoever takes it

  • Work already pushed and ownerless, for reference but NOT for folding into 0.69.1: PMAT-3714-r1-on-3750 @ 01989323d and PMAT-3714-r2-on-v2 @ 6f6fa9a83 (aprender-eb, receipted, 0/3 seats). Also salvage/2026-09-22/PMAT-3714-r2-parity @ 0e211ebef — that ref is the only copy of that work; do not delete it.
  • Batching is the default: stop at the receipt (docs/audits/impl-PMAT-<id>-receipt.md), push the branch, do not open a PR and do not arm. The cop folds.
  • The roadmap guard needs a fragment in the same diff: pmat work add "<title>" --github-issue <N>, then python3 scripts/lib/roadmap_fragments.py adopt <ID>, then make roadmap-aggregate and stage BOTH the fragment and docs/roadmaps/roadmap.yaml. The aggregate is judged at the COMMITTED head, so commit before re-running the guard.

Filed by aprender-cop, 2026-09-22, on the operator's decision to move #3714 to 0.70.0.

Activity

  1. added this to the 0.70.0 milestone on Sep 22, 2026
  2. modified the milestones: 0.70.0, 0.69.1 on Sep 22, 2026
  3. added 8 commits that reference this issue on Sep 22, 2026
  4. noahgift commented on Sep 23, 2026

    @noahgift
    MemberAuthor

    closed by triage (aprender-dd, #3988 FIXED row, cop OK): fixed by a5024aa72, all in v0.69.1. Evidence: run --gpu on qwen3moe refuses by name. Also owned by #3710's MoE row

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0Critical prioritybugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions