---
version: 0.15.1
date: 2026-06-18
headline: "Harden llama3 RoPE-scaling: a malformed rope_scaling config now fails loud at Load instead of silently emitting NaN logits."
themes:
  - fak
  - model
  - long-context
highlights:
  - "An adversarial review of v0.14.0 found a malformed llama3 config built an all-NaN, permanently-cached inv_freq table — silent garbage output."
  - "RopeScaling.validate() enforces HF's parameter requirements; Load now fails loud (error naming rope_scaling), matching HF's KeyError."
  - "scaleInvFreq defends with a base-table fallback so a directly-constructed malformed Config never poisons the cache with NaN/Inf."
  - "4 new tests: regime-boundary semantics, the validate predicate, malformed-falls-back-to-base, and Load loud-rejection."
  - "No-op invariant and the bit-exact rungs are unchanged; the v0.14.0 default path stays byte-identical."
---

**TL;DR** — a patch release hardening v0.14.0's llama3 RoPE-scaling. An adversarial
verification pass found that a `rope_type:"llama3"` config *missing* its numeric
fields (a truncated or hand-written `config.json`) unmarshalled to Go zero-values and
built an **all-NaN** `inv_freq` table — which the process-global cache then served
forever, silently turning every logit into NaN. HuggingFace raises a loud `KeyError`
on the same config; fak now matches that fail-loud behavior. No new capability; no
change to the proven default path.

## Fail loud on a malformed rope_scaling (#fak #model #long-context)

- **What changed** — `RopeScaling.validate()` enforces HF's parameter requirements
  (`factor>0`, `0<low_freq_factor<high_freq_factor`, `original_max_position_embeddings>0`).
  `Load` calls it right after reading `config.json` and returns a descriptive error
  naming `rope_scaling`, so the real-checkpoint path **fails loudly at load**, not
  silently at decode. As defense-in-depth, `scaleInvFreq` falls back to the base
  (unscaled) table for a directly-constructed malformed `Config` rather than poisoning
  the cache with NaN/±Inf.
  - *Why:* the project's stance is fail-loud, never silently wrong (the policy
    philosophy in `CLAIMS.md`). A silently-cached NaN table that corrupts every token
    is exactly the anti-pattern.
  - *How:* `internal/model/rope_scaling.go` (`validate` + the guard),
    `internal/model/weights.go` (`Load`). The `low<high` ordering check also keeps the
    high/medium/low switch a faithful collapse of HF's `torch.where` — which it is *not*
    for an inverted `low>high` config — subsuming that divergence and the
    `factor==0 → +Inf` edge case the review also flagged.
- **New tests** (`go test ./internal/model -run Rope`, green):
  - `TestLlama3RopeScalingBoundaries` — pins the strict-`<` vs `<=` regime boundaries
    (wavelen == high/low wavelen) against HF; the real table never lands on a boundary,
    so this is the only guard against a `<`→`<=` edit silently diverging.
  - `TestRopeScalingValidate` — the loud-failure predicate (malformed rejected; nil /
    unwired type / real Llama-3.1 values pass).
  - `TestLlama3MalformedFallsBackToBase` — a malformed config never poisons the table.
  - `TestLoadRejectsMalformedLlama3RopeScaling` — `Load` errors instead of loading a
    NaN-emitting model.
- **Unchanged** — the no-op invariant (nil/unwired `RopeScaling` is byte-identical) and
  every bit-exact rung (R2/R14/HF-oracle/Q8) are untouched; this only adds a guard on
  the malformed path. `RopeScaling` is now documented as immutable-after-`Load`.

## Also in this release

- **Known device-lane gap, tracked honestly** — the rescale reaches every CPU lane (it
  routes through the single `invFreq` builder), but the two *device* RoPE paths
  (compute-HAL `hal.go`, Metal-resident `metal_prefill.go`) still build `inv_freq` from
  `θ` alone, so a scaled config silently runs base RoPE through them. The device wiring
  (and, until then, a guard that errors rather than running base RoPE) is the peer-lane
  follow-up. Documented in `fak/ROPE-SCALING-RESULTS.md` and `CLAIMS.md`.
- **Next-rung handoff** — a verified **longrope (#23)** implementation design (the
  per-dim `inv_freq` rescale + the `attention_factor` mscale + the session-start regime
  pin) is recorded in `fak/ROPE-SCALING-RESULTS.md` for the next increment.
