llama.cpp Flags Explained (2026): --no-mmap Is Now -lm none
Most llama.cpp guides copy a command line from a forum post and never say what the flags do. That worked until 2026, when the flag set changed underneath everyone. --no-mmap and --mlock are gone, -ngl defaults to auto instead of 0, and -fa decides for itself. Here is what every flag that matters actually does, which ones buy speed, which ones only buy memory, and which commands on the internet now fail outright.
Bottom Line (2026)
- Three flags changed underneath everyone in 2026.
--no-mmap,--mlockand--direct-iowere folded into-lm, --load-mode(PR #20834, merged 2026-07-23), kept as deprecated aliases, then removed outright in PR #28334 on 2026-09-09. Any build from b10875 onward rejects them witherror: invalid argument. - Pasted an error? Go straight to every
error: invalid argumentand its fix. It covers--no-mmap,--mlock,-cd,-cnv,--ngl,--ctx-shiftand the llama-bench-mmpflag. -nglnow defaults toauto. The advice to always pass-ngl 99is a workaround for a default that no longer exists.- Separate the memory flags from the speed flags. This is the distinction almost nobody writes down, and it is why people set KV cache quantization expecting a speed-up and measure a slow-down.
- Only two flags reliably buy you speed on a machine that already fits the model:
-faand-ub. Everything else buys you the ability to run the model at all. - A current build may shrink your context without telling you.
-fitdefaults toonand lowers unset arguments,-cfirst, until the model fits. Pass-fit offwhen you benchmark. Checked against the v0.9.0 README on 2026-11-04. - Do not copy a
--n-cpu-moevalue. Sweep it. See llama.cpp MoE Offload Flags Explained for the method.
The Flag Table
Flag spellings and defaults below are quoted from the llama-server README, first on 2026-09-15 and re-checked on 2026-11-04 against the v0.9.0 release. Every default in the September table still holds. Six flags are new since then; they are marked new. Check your own build with llama-server --help; this project moves fast.
| Flag | What it does | Default | Buys you |
|---|---|---|---|
-ngl, --gpu-layers, --n-gpu-layers N | Max layers stored in VRAM. Takes a number, auto, or all | auto | Fit |
-lm, --load-mode MODE | How the model is loaded: auto, none, mmap, mlock, mmap+mlock, dio | auto | Fit |
-fa, --flash-attn [on|off|auto] | Flash Attention | auto | Speed |
-fit, --fit [on|off] new | Adjusts arguments you did not set so the model fits in device memory | on | Fit, silently |
-fitc, --fit-ctx N new | Smallest context --fit may pick | 4096 | Fit |
-fitt, --fit-target MiB,... new | Memory margin per device that --fit keeps free | 1024 | Fit |
-lzm, --lazy-mode MODE new | Reads large tensors, such as per-layer embeddings, from disk on demand: on, auto, off. Needs mmap | auto (on above 4 GiB) | Fit |
--cpu-moe, -cmoe | Keeps all MoE weights in CPU RAM | off | Fit |
--n-cpu-moe N, -ncmoe | Keeps MoE weights of the first N layers in CPU RAM | off | Fit |
-ncffn, --n-cpu-ffn N new | The dense-model twin of --n-cpu-moe: keeps the FFN weights of the first N layers in CPU RAM | off | Fit |
--moe-cache-mib N new | GPU cache, in MiB, for the experts you kept in CPU RAM. Split across GPUs like -ts | 0 (off) | Speed for MoE offload |
-c, --ctx-size N | Prompt context size. 0 reads it from the model | 0 | Fit |
-b, --batch-size N | Logical max batch size | 2048 | Little |
-ub, --ubatch-size N | Physical max batch size — sizes the compute buffers | 512 | Speed / fit |
-dt, --defrag-thold N | KV cache defragmentation threshold. Marked DEPRECATED in the README | — | Nothing. Delete it |
--cache-type-k TYPE | KV cache type for K: f32, f16, bf16, q8_0, q4_0, q4_1, iq4_nl, q5_0, q5_1 | f16 | Fit |
--cache-type-v TYPE | KV cache type for V | f16 | Fit |
-kvo/-nkvo, --kv-offload/--no-kv-offload | Whether the KV cache lives on the GPU | enabled | Fit |
--swa-full | Use a full-size sliding-window-attention cache | false | Fit |
-np, --parallel N | Number of server slots (concurrent requests) | -1 (auto) | Throughput |
-sm, --split-mode {none,layer,row,tensor} | How a model splits across several GPUs | layer | Fit |
-ts, --tensor-split N0,N1,... | Fraction of the model sent to each GPU | even | Fit |
-ot, --override-tensor <pattern>=<type> | Per-tensor buffer placement | off | Fit |
-dev, --device <dev1,dev2> | Which devices to offload to | all | Control |
-t, --threads N | CPU threads used during generation | -1 (auto) | Speed on CPU |
--numa TYPE | NUMA optimizations on multi-socket machines | off | Speed on CPU |
-n, --predict N | Tokens to predict. -1 is unlimited | -1 | — |
--jinja / --no-jinja | Jinja chat template engine | enabled | Correctness |
Memory Flags and Speed Flags Are Not the Same Thing
This is the distinction that makes the table usable.
A memory flag changes whether the model runs at all. -ngl, -c, --cache-type-k, --cache-type-v, --n-cpu-moe, -ts and --swa-full all trade something away so the weights and the cache fit in the memory you own. Most of them make generation slower. You accept that, because the alternative is not running.
A speed flag changes tokens per second on a model that already fits. There are far fewer of these than the internet implies. -fa on is the reliable one. -ub helps prompt processing when you raise it and helps VRAM fit when you lower it. -t matters when the CPU is doing real work, which now includes every MoE offload setup.
The practical consequence: quantizing your KV cache will not speed anything up. --cache-type-k q8_0 is a memory feature. It frees VRAM so you can raise -c, and it adds conversion work on every token. If f16 fits, f16 is faster. People try it as a performance tweak, measure a regression, and conclude llama.cpp is unpredictable. It is not; the flag was never a speed flag.
The 2026 Breaking Change: --no-mmap and --mlock Are Gone
If you have hit error: invalid argument on a command that worked last year, this is almost certainly why.
llama.cpp collapsed four separate loading flags into one. -lm, --load-mode MODE now takes:
| Mode | Behaviour |
|---|---|
auto | mmap, unless a device does not support it. The default |
none | No special loading mode. This is the old --no-mmap |
mmap | Memory-map the model |
mlock | Force the system to keep the model in RAM rather than swapping it |
mmap+mlock | Both |
dio | Use DirectIO where available |
The migration table is short:
| Old flag | Write this instead |
|---|---|
--no-mmap | -lm none |
--mlock | -lm mlock |
--mmap | -lm mmap |
--direct-io | -lm dio |
The honest caveat nobody publishes with the migration table. The new enum treats mlock as always implying mmap, so the old --no-mmap --mlock combination has no replacement. That combination mattered specifically to MoE offload users: it loaded weights into ordinary heap buffers while stopping the kernel swapping out the CPU-resident expert tensors. Issue #26110, opened 2026-07-25 and still open at the time of writing, reports the consequence — -lm none lets CPU-resident weights get swapped out under load, with throughput falling from roughly 25-27 tok/s to 7.55 tok/s, while -lm mlock double-buffers the model and invites the OOM killer.
If you run a large MoE with --n-cpu-moe on a machine that is tight on RAM, test both modes and watch swap. There is currently no setting that gives you what the old pair gave you.
Every error: invalid argument and Its Fix
All of these come from one line in llama.cpp’s argument parser. The parser keeps a separate flag list for each binary. If a word on your command line is not in the list for the binary you ran, it stops with error: invalid argument: <word>. So the error means one of three things. The flag was removed, the flag belongs to a different binary, or the flag is misspelled.
| You see | Cause | Fix | Changed in |
|---|---|---|---|
error: invalid argument: --no-mmap | Flag removed | -lm none | PR #28334, b10875 |
error: invalid argument: --mlock | Flag removed | -lm mlock | PR #28334, b10875 |
error: invalid argument: --mmap | Flag removed. mmap is already the default | Delete it, or -lm mmap | PR #28334, b10875 |
error: invalid argument: --direct-io | Flag removed | -lm dio | PR #28334, b10875 |
error: invalid parameter for argument: -mmp | llama-bench dropped -mmp and -dio | -lm none or -lm mmap | PR #28334, b10875 |
error: invalid argument: -cd | --ctx-size-draft removed | Delete it. No replacement | PR #22838, b9109 |
error: invalid argument: -cnv | Legacy flag. Not in the new llama-cli | Run llama-completion | PR #17824, b7348 |
error: invalid argument: --ngl | Misspelled long form | -ngl 99 or --n-gpu-layers 99 | Never valid |
error: invalid argument: --ctx-shift | Misspelled | --context-shift | Never valid |
error: unknown value for --flash-attn | -fa now needs a value | -fa on | PR #15434, b6325 |
error: invalid argument: 1 | A value after a flag that takes none | Delete the value | Not a change |
Release numbers are the first tagged build that carries the change. Run llama-server --version to see yours.
error: invalid argument: —no-mmap (and —mlock, —mmap, —direct-io)
The four loading flags are gone. PR #20834 merged -lm, --load-mode on 2026-07-23 and kept the old names as deprecated aliases. The first release with it is b10105. PR #28334 then deleted the aliases on 2026-09-09. Its author wrote that it had been “a decent amount of time since we deprecated” them. The first release without them is b10875.
The fix is a one-word swap:
# before (fails on b10875 and later)
llama-server -m model.gguf --no-mmap -ngl 99
# after
llama-server -m model.gguf -lm none -ngl 99
The silent version of this error. Docker and systemd setups often pass flags as environment variables. LLAMA_ARG_MMAP, LLAMA_ARG_NO_MMAP and LLAMA_ARG_MLOCK belonged to the removed flags. The parser reads an environment variable only when a current flag declares it, so these three are now ignored with no warning. Your server starts, and it loads the model with the default mmap mode. Replace them with LLAMA_ARG_LOAD_MODE=none or LLAMA_ARG_LOAD_MODE=mlock.
If you used --no-mmap --mlock together, read the caveat in the section above. That pair has no exact replacement.
error: invalid parameter for argument: -mmp
This is the llama-bench version of the same change. llama-bench has its own parser and its own error text. PR #28334 removed -mmp, --mmap and -dio, --direct-io from it too. Use -lm none where you had -mmp 0, and -lm mmap where you had -mmp 1. The -lm option in llama-bench accepts a comma-separated list, so you can still compare modes in one run.
error: invalid argument: -cd
-cd was --ctx-size-draft: the context size for the draft model in speculative decoding. It was a real llama-server flag. PR #22838 reworked speculative decoding for parallel drafting and deleted it on 2026-05-11. The first release without it is b9109. The current argument list has no draft context size flag, so delete it from your command line.
Older draft flags fail with a different message, because llama.cpp kept stubs for them. --draft, --draft-n, --draft-max and --draft-min now print the argument has been removed. use --spec-draft-n-max or --spec-ngram-mod-n-max (or the -n-min pair). The message names the replacement, so follow it.
error: invalid argument: -cnv (and -i, -if, -gan)
You are running the new llama-cli. PR #17824 rebuilt llama-cli on top of llama-server on 2025-12-10 (first release b7348). The old program still exists, renamed llama-completion. Conversation mode (-cnv, -no-cnv), interactive mode (-i, -if) and group attention (-gan, -gaw) are registered only for llama-completion in the current parser.
# old tutorial command
llama-cli -m model.gguf -cnv
# same behaviour today
llama-completion -m model.gguf -cnv
The new llama-cli is a chat program by default, so most people can drop -cnv and keep llama-cli.
error: invalid argument: —ngl
The short flag has one dash: -ngl. The long forms are --gpu-layers and --n-gpu-layers. A maintainer gave exactly this answer in issue #23739. As of 2026, -ngl defaults to auto, so you can often delete it.
error: invalid argument: —ctx-shift
The flag is spelled --context-shift, and its opposite is --no-context-shift. Both are valid for llama-server and llama-cli. --ctx-shift is not in the parser.
error: unknown value for —flash-attn
-fa used to be an on/off switch with no value. PR #15434 changed it on 2025-08-30 to take on, off or auto (first release b6325). An old command with a bare -fa now hands the next word to -fa as its value. Write -fa on, or delete the flag, because the default is auto.
error: invalid argument: 1 (or any number)
The parser read a value as if it were a flag name. The flag before it takes no value. --jinja 1 fails this way, because --jinja is a switch: write --jinja or --no-jinja. Look at the word just before the one in the error.
The rule for anything not listed here
Run the binary with --help and search for the flag. Do not check it against a tutorial or against another binary’s README. A flag that works in llama-server can be invalid in llama-cli, llama-completion or llama-bench, because each binary registers its own list.
The Flags Added Since September: -fit, --lazy-mode, --moe-cache-mib
Three of the six new flags change what a copied command does, so they get their own section. All quotes are from the README on 2026-11-04.
-fit, --fit [on|off] — “whether to adjust unset arguments to fit in device memory”, default on. This is the one to know about. On a current build the server looks at your device memory and lowers arguments you did not set, context first, until the model fits. It does not error and it does not ask. So a model that “runs fine” may be running at 4,096 tokens of context, the --fit-ctx floor, instead of the 128K you assumed. Two consequences:
- When you benchmark, pass
-fit off. Otherwise two machines with the same command line can run different contexts and different batch sizes, and your numbers will not compare. - When the model does not fit even at the floor, you still get the old out-of-memory failure.
-fitlowers settings; it does not offload for you.
-fitt, --fit-target sets the margin --fit keeps free per device, in MiB, default 1024. -fitc, --fit-ctx sets the smallest context it may choose, default 4096. Search Console shows people already typing --fit off into Google; this is the flag they are looking for.
-lzm, --lazy-mode MODE — “on-demand reading of certain tensors, for example per-layer embeddings”, default auto, which the README defines as “on, but only for tensors larger than 4 GiB”. The README says it “requires mmap”, so it cannot work under -lm none. The target is models with huge per-layer embedding tables, Gemma-style, where a 4 GiB table would otherwise sit in RAM for the whole session.
--moe-cache-mib N — “GPU cache size in MiB for the MoE experts kept in the CPU”, default 0, disabled. It is the partner of --n-cpu-moe: the experts you pushed to system RAM get a GPU-side cache, so the hot ones stop crossing the bus every token. With several GPUs it is “split among them like the layers”. This is the only new flag that buys speed, and only for MoE offload setups. Start it at a few thousand MiB and sweep, the same way you swept --n-cpu-moe.
-ncffn, --n-cpu-ffn N — the dense-model twin of --n-cpu-moe: “keep the dense FFN weights of the first N layers in the CPU”. Use it on a dense model that is a few GB over your VRAM. The README says plainly: “for MoE expert weights use —n-cpu-moe”.
The v0.9.0 release itself, tagged 2026-11-04, added an OCP FP8 E4M3 tensor type and a new ftype, LLAMA_FTYPE_MOSTLY_F8_E4M3. That is a file format, not a flag: nothing in this table changed for it.
The Flags Worth Setting By Hand
Everything defaults sensibly now. These are the ones still worth a deliberate value.
-c, --ctx-size— the default reads the model’s trained context, which on a modern model can be enormous and will reserve VRAM to match. Set it to the context you actually use. This is the single most common cause of “it used to fit.”-fa on— leaving it onautois fine, but pin itonwhen you are benchmarking, so a build-to-build change in the auto heuristic does not silently move your numbers.-ub— lower it to256when you are a few hundred megabytes short of fitting. Raise it when prompt processing is your bottleneck and VRAM is not.--n-cpu-moe N— for MoE models only, and only after a sweep.-np, --parallel— raise it only if you genuinely serve concurrent requests. Each slot reserves its own KV cache, so raising it on a single-user machine costs VRAM and returns nothing.-fit off— for any run whose number you intend to compare with another run.
How to Find Your Own Numbers
The values in every guide, including this one, came off somebody else’s machine. Quant, RAM speed, context length, GPU and CPU all move them. The method transfers; the numbers do not.
- Start from defaults. Set
-cto the context you need and pass-fit off, so the server does not move your settings between runs. - Change one flag. Measure tokens per second on a fixed prompt.
- Watch VRAM while you do it. The cliff where VRAM spills into driver-managed system memory is sharp, and on many systems it produces no error message at all — just a collapse in speed.
- When speed collapses, back off one step and stop.
Which card you own decides how many of these flags you ever need — most of the memory flags exist to work around VRAM you do not have.
Sources
- llama-server README, “Common params” and “Server-specific params” tables, read 2026-09-15 and re-read 2026-11-04. Every quoted description and default comes from there.
- llama.cpp v0.9.0 release notes, tagged 2026-11-04: FP8 E4M3 ftype, no argument changes.
- Removal history: PR #20834, PR #28334, PR #22838, PR #17824, PR #15434, and issue #26110 for the
-lm noneswap caveat.
See Also
- llama.cpp MoE Offload Flags Explained — the deep dive on
--n-cpu-moe, with measured sweeps - Why Local LLMs Are Slow Even When They Fit — the bandwidth ceiling no flag can raise
- KV Cache Quantization: q8 vs q4 and VRAM — how much context each cache type buys
- How Much VRAM for 128K Context? — sizing
-cbefore you set it - IQ4_XS vs Q4_K_M vs Q4_K_XL — picking the quant that fits the VRAM you have
- vLLM vs llama.cpp vs SGLang — when the flags are not the problem and the engine is
- Why Is My Local LLM So Slow? — the diagnostic order to work through first
- AMD ROCm Setup for Local LLMs — prebuilt ROCm and Vulkan builds of llama.cpp, and the Strix Halo
-lm nonedefault