Commit e49d2c276 for llama.cpp
commit e49d2c27605ec3c5b299b9583fa8dc0442739e18
Author: Yaniss Amazouz <yaniss91600@gmail.com>
Date: Sun Sep 13 20:20:50 2026 +0300
models : guard the expert FFN size fallback in nemotron-h against a zero divisor (#28779)
The NextN/MTP tail loop derives the expert FFN size as n_ff/n_expert_used
when expert_feed_forward_length gives nothing for the layer. Both values come
from per-layer arrays that legitimately hold 0 on layers that are not MoE, so
a checkpoint whose predict layers hold 0 in both divides by zero and dies with
SIGFPE at load time, with no error message. Report the malformed metadata
instead.
diff --git a/src/models/nemotron-h.cpp b/src/models/nemotron-h.cpp
index d2c48f125..ff8784d18 100644
--- a/src/models/nemotron-h.cpp
+++ b/src/models/nemotron-h.cpp
@@ -145,8 +145,14 @@ void llama_model_nemotron_h::load_arch_tensors(llama_model_loader & ml) {
const int64_t n_head_i = hparams.n_head(i);
const int64_t n_embd_k_gqa_i = hparams.n_embd_k_gqa(i);
const int64_t n_embd_v_gqa_i = hparams.n_embd_v_gqa(i);
- const int64_t n_ff_exp = hparams.n_ff_exp(i) ? (int64_t)hparams.n_ff_exp(i) : n_ff / (int64_t)hparams.n_expert_used(i);
- const int64_t n_ff_shexp = hparams.n_ff_shexp;
+ const int64_t n_expert_used_i = hparams.n_expert_used(i);
+ const int64_t n_ff_exp_i = hparams.n_ff_exp(i);
+ if (n_ff_exp_i == 0 && n_expert_used_i == 0) {
+ throw std::runtime_error(format("%s: layer %d declares neither expert_feed_forward_length nor expert_used_count, "
+ "cannot determine the expert FFN size", __func__, i));
+ }
+ const int64_t n_ff_exp = n_ff_exp_i ? n_ff_exp_i : n_ff / n_expert_used_i;
+ const int64_t n_ff_shexp = hparams.n_ff_shexp;
// NextN input-fusion tensors
layer.nextn.enorm = create_tensor(tn(LLM_TENSOR_NEXTN_ENORM, "weight", i), {n_embd}, mtp_flags);