# Risk map — deepseek-ai/DeepSeek-V3

> Canonical page: https://codevetter.com/unpack/deepseek-v3/risk-map

# Risk map — deepseek-ai/DeepSeek-V3

Scanned commit 9b4e9788e4a3a731f7567338ed15d3ec549ce03b (2025-08-28). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

The codebase is a demo, and its risks match: correctness depends on runtime asserts (stripped under -O), module-level globals that must be set before model construction, a hardcoded dim==7168 special case in Gate, and silent behaviors like dropping all layer-61 (MTP) weights during conversion. The distributed path uses pickle-based broadcast_object_list and suppresses stdout on non-zero ranks. Memory is pre-allocated aggressively (full-length KV caches). There is no input validation on paths and no test coverage anywhere.
- Gate creates its correction bias only when self.dim == 7168 — a magic-number coupling to the 671B config; any other model dim that needs e_score_correction_bias (e.g., V3.1-style variants on different dims) would silently load-mismatch. — [inference/model.py#L563-564](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/model.py#L563-L564)
- world_size, rank, gemm_impl, attn_impl, and block_size are module-level globals in model.py; world_size/rank are only (re)assigned inside Transformer.__init__, so constructing modules before the Transformer or changing impl flags post-hoc gives stale values. — [inference/model.py#L13-17](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/model.py#L13-L17) [inference/model.py#L757-759](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/model.py#L757-L759)
- gemm_impl and attn_impl are not exposed as CLI flags in generate.py — changing them requires editing model.py, and nothing validates the combination against the loaded checkpoint dtype. — [inference/model.py#L16-17](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/model.py#L16-L17) [inference/generate.py#L176-185](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/generate.py#L176-L185)
- main() rebinds the builtin name 'print' to a no-op lambda on non-zero ranks via 'global print' — any library code or later edits relying on print on those ranks are silently swallowed. — [inference/generate.py#L105-107](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/generate.py#L105-L107)
- convert.py unconditionally skips every tensor containing 'model.layers.61', silently discarding the MTP module weights without warning. — [inference/convert.py#L53-54](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/convert.py#L53-L54) [README_WEIGHTS.md#L46-48](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/README_WEIGHTS.md#L46-L48)
- Interactive mode synchronizes ranks with dist.broadcast_object_list, which pickles Python objects over the wire — acceptable for a trusted torchrun cluster but unsafe if any peer is untrusted. (inferred) — [inference/generate.py#L128-133](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/generate.py#L128-L133)
- User-supplied paths (--ckpt-path, --config, --input-file, --hf-ckpt-path, --save-path) are used directly in open()/glob()/os.makedirs with no validation; this is a CLI tool so impact is limited to the invoking user's privileges. (inferred) — [inference/generate.py#L112](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/generate.py#L112) [inference/generate.py#L146](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/generate.py#L146) [inference/convert.py#L50](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/convert.py#L50) [inference/convert.py#L78](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/convert.py#L78)
- Validation is assert-based throughout (CLI arg checks, batch-size limit, divisibility, contiguity); running under python -O strips all of it, turning config errors into shape mismatches deep in the forward pass. — [inference/generate.py#L148](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/generate.py#L148) [inference/generate.py#L184](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/generate.py#L184) [inference/kernel.py#L51-52](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/kernel.py#L51-L52) [inference/convert.py#L95](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/convert.py#L95)
- KV caches are allocated at construction as zeros(max_batch_size, max_seq_len, ...) — with defaults max_seq_len=16384 that's a large always-on GPU allocation per layer regardless of actual prompt lengths. — [inference/model.py#L439-444](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/model.py#L439-L444) [inference/model.py#L55-56](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/model.py#L55-L56)
- The MoE expert dispatch is a Python loop over experts with torch.where gather per expert — O(n_routed_experts) kernel launches per layer per step; correct but far from production performance (README itself steers users to SGLang/vLLM). — [inference/model.py#L683-689](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/model.py#L683-L689) [README.md#L229-238](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/README.md#L229-L238)
- weight_dequant inside the absorb attention path runs every forward step when wkv_b is FP8 (wkv_b.scale is not None), dequantizing the full kv_b weight per decode step — a hidden per-token cost. — [inference/model.py#L481](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/model.py#L481)
- sample() divides probs in-place by an exponential_ tensor (probs.div_); logits are also divided by max(temperature,1e-5) — correct Gumbel-max sampling, but in-place mutation of freshly computed probs is fragile if reused. (inferred) — [inference/generate.py#L25-27](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/generate.py#L25-L27)
- fp8_cast_bf16 loads entire safetensor files to cuda and caches up to 2 files; on machines with less VRAM than 2 shards this OOMs, and the 'missing scale_inv' path only prints a warning while still writing the FP8 weight into a 'BF16' checkpoint. — [inference/fp8_cast_bf16.py#L60-94](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/fp8_cast_bf16.py#L60-L94)
- generate() pads the token buffer with -1 and relies on prompt_mask; if a batch mixes prompt lengths, positions before min(prompt_lens) are forced from the buffer — correct, but the loop can never start before min(prompt_lens), so shorter prompts waste no steps while all sequences share total_len. — [inference/generate.py#L54-66](https://github.com/deepseek-ai/DeepSeek-V3/blob/9b4e9788e4a3a731f7567338ed15d3ec549ce03b/inference/generate.py#L54-L66)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
