[BUG] 2.1.120 interactive --resume crashes: `UKH is not a function` (RW4 stub missing onSessionRestored)

Resolved 💬 5 comments Opened Apr 25, 2026 by JadenJ09 Closed Apr 27, 2026

Summary

Claude Code 2.1.120 interactive --resume (and any flow that loads non-empty initialMessages) crashes immediately with:

ERROR  UKH is not a function. (In 'UKH(K)', 'UKH' is undefined)

Stack anchor: cli.js:9247:5663 (REPL QC6 mount effect).

Downgrading to 2.1.119 makes the same command work.

Environment

  • Claude Code: 2.1.120 (broken) · 2.1.119 (works)
  • Platform: Linux 6.12.73+deb13-amd64 (Debian 13)
  • Bun-bundled native build (/home/$USER/.local/share/claude/versions/2.1.120)
  • Plan: paid (auto-mode enabled · --enable-auto-mode)

Repro

claude --resume
# pick any prior session whose JSONL has K.length > 0 messages

Crash fires before any user input. Headless claude -p '<prompt>' is unaffected (different code path that doesn't preload initialMessages).

Root cause (binary analysis)

In 2.1.120's cli.js, the REPL component QC6 destructures onSessionRestored from the RW4 hook:

let { onBeforeQuery:FKH, onTurnComplete:vvH, onSessionRestored:UKH, render:sJ$, ownsInput:VvH }
  = RW4({ enabled:I, setMessages:F7, setInputValue:G_, setToolJSX:oK, resultDedupState:RF.current });

Then unconditionally calls UKH(K) in a mount effect when initialMessages is non-empty:

useEffect(() => {
  if (K && K.length > 0) {
    $L$(K, K6());
    yO6({...});
    eR6(K);
    Bc(K);
    tOH.current.current = u3$(K, U6);
    UKH(K);   // ← undefined when RW4 returns the disabled stub
  }
}, []);

But RW4's body in 2.1.120 returns a stub with only 3 fields:

function RW4(H){
  return {
    onBeforeQuery: async()=>!0,
    onTurnComplete: async()=>{},
    render: ()=>null
  }
}

onSessionRestored and ownsInput are missing. Combined with I = useMemo(()=>!1, []) always being false, the disabled-stub path is the only path, so UKH (and VvH) are guaranteed undefined.

Diff vs 2.1.119

Binary grep on the two stripped binaries (no obfuscation difference, same minifier):

| Pattern | 2.1.119 (43950e9b…) | 2.1.120 (a6c8e91e…) |
|:--|:-:|:-:|
| UKH(K) call sites | 0 | 2 |
| onSessionRestored:UKH destructure | 0 | 2 |
| onSessionRestored substring | 0 | 3 |

So 2.1.120 introduced both the destructure and the call site, but the producer (RW4) was not extended to actually return the field. Looks like a partial refactor that shipped without the matching hook update.

Suggested fix

Either:

  1. Add onSessionRestored (and ownsInput) to the RW4 disabled-stub return value (no-op () => {}), or
  2. Guard the call: UKH?.(K) in the mount effect.

(2) is the smaller diff and removes a class of similar regressions.

Workaround for affected users

# Pin to 2.1.119 (last known good)
ln -sfn ~/.local/share/claude/versions/2.1.119 ~/.local/bin/claude
# Optionally disable auto-update channel to prevent re-pull

Tested clean on 2.1.119 with same alias / same session JSONL.

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗