Skip to content

Deterministic SIGSEGV in sequence-checkpoint init on Metal for hybrid / SWA models (Qwen3.5, Gemma 3) #630

Description

@jb-ao

Description

AddonContextSequenceCheckpointInitWorker crashes the Node process with SIGSEGV on macOS/Metal whenever a model with needsCheckpoints === true (hybrid or sliding-window architecture) evaluates its first prompt. The crash is 100% reproducible for us across two unrelated model families and survives reboots; plain-attention models (Mistral family) never crash because the checkpoint path is never taken.

Environment

  • node-llama-cpp 3.19.0 (prebuilt Metal binary, libllama.metal.b9842.dylib)
  • macOS 26.5.1 (Darwin 25.5.0), Apple M1, 8 GB unified memory
  • Node v22.17.1
  • Models (both Q4_K_M GGUF):
    • unsloth/Qwen3.5-4B-GGUFQwen3.5-4B-Q4_K_M.gguf (hybrid attention)
    • bartowski/google_gemma-3-4b-it-GGUFgoogle_gemma-3-4b-it-Q4_K_M.gguf (sliding-window attention)

Reproduction

import { getLlama, LlamaChatSession } from 'node-llama-cpp';

const llama = await getLlama();
const model = await llama.loadModel({ modelPath: 'Qwen3.5-4B-Q4_K_M.gguf' });
const context = await model.createContext({ contextSize: 4096 });
const session = new LlamaChatSession({ contextSequence: context.getSequence() });
// Any prompt long enough for generation to start; crashes when the
// initial/interval checkpoint is taken during evaluation:
await session.promptWithMeta('<a few hundred tokens of text>', { temperature: 0.2, maxTokens: 400 });
// -> process dies with SIGSEGV, no JS error

Crashes every time (6/6 across the two models on our machine), including immediately after a clean reboot with ~0 swap in use, so it is not memory pressure.

Crash stacks (from macOS DiagnosticReports)

Qwen3.5-4B (hybrid) — KERN_INVALID_ADDRESS at 0x0000000000000250:

libllama.metal.b9842.dylib  llama_context::synchronize()
libllama.metal.b9842.dylib  llama_state_seq_get_data_ext
llama-addon.node            AddonContextSequenceCheckpointInitWorker::Execute()
llama-addon.node            Napi::AsyncWorker::OnExecute(Napi::Env)

Gemma-3-4B-it (SWA) — KERN_INVALID_ADDRESS in memmove:

libsystem_platform.dylib    _platform_memmove
libllama.metal.b9842.dylib  llama_io_write_host::~llama_io_write_host()
libllama.metal.b9842.dylib  llama_context::state_seq_get_data(int, unsigned char*, unsigned long, unsigned int)
llama-addon.node            AddonContextSequenceCheckpointInitWorker::Execute()
llama-addon.node            Napi::AsyncWorker::OnExecute(Napi::Env)

Full .ips crash reports available on request (six of them: three per model).

Analysis / notes

  • LlamaContextSequence.needsCheckpoints returns true for isHybrid || isRecurrent and for SWA models without swaFullCache — matching exactly the two families that crash. _takeCheckpoint() then constructs AddonContextSequenceCheckpoint and its init() ends up in llama_state_seq_get_data(_ext), which appears to be unsafe for these KV-cache types on Metal in the bundled llama.cpp build (possibly related to upstream issues about seq-state save/restore for hybrid/recurrent and iSWA caches).
  • Workaround that works for SWA models: createContext({ swaFullCache: true })needsCheckpoints goes false and everything runs normally (verified with a full 40-generation benchmark on the Gemma model above).
  • No workaround found for hybrid models: needsCheckpoints is unconditionally true for them, and both the initial checkpoint in LlamaChat and interval checkpoints reach the crashing init, so Qwen3.5-family models are currently unusable with 3.19.0 on Metal for us.

Thanks for the great library — happy to attach crash reports or test a patched build.

Activity

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions