whisper.cpp: “failed to load model”
8 min read · updated August 11, 2026
whisper.cpp prints a load failure as a stack of three lines, and only the middle one tells you anything. Read that line and the three causes separate immediately.
The strings
The shape you get is the loader’s own diagnosis, then the initialiser giving up, then the CLI:
whisper_init_from_file_with_params_no_state: loading model from 'models/ggml-base.en.bin' whisper_init_from_file_with_params_no_state: failed to open 'models/ggml-base.en.bin' error: failed to initialize whisper context
The second line is the variable one. Across the codebase the loader can report, among others: failed to open, invalid model data (bad magic), invalid model (bad ftype value), unknown tensor '...' in model file, tensor '...' has wrong size in model file, tensor '...' has wrong shape in model file, and ERROR not all tensors loaded from model file. Each of those is a check at a different depth of the file, and how far the loader got is exactly the information you need.
Failure one: it could not open the file
failed to open means the process could not read the path. Not that the model is wrong — that the operating system said no. The loader has not looked at a single byte of content.
- A relative path against the wrong working directory. The quick-start commands use
models/ggml-base.en.bin, which resolves relative to wherever the shell is, not to where the binary is. Running the same command from a build subdirectory or through a GUI wrapper changes the answer. Test with an absolute path first; this resolves a surprising share of reports, including ones where the file is visibly present in a file manager. - Permissions. A model downloaded as one user and read by a service running as another, or a file inside a directory the process cannot traverse.
- A download script that wrote nothing.
models/download-ggml-model.shcan leave a zero-byte or HTML-error file behind when the fetch fails. Check the size before anything else — a real base model is on the order of a hundred megabytes, not a hundred bytes.
Failure two: bad magic
whisper_model_load: invalid model data (bad magic)
The file opened, and its first four bytes are not the ggml magic number. A magic number is a fixed constant at the head of the file whose only job is to let a reader reject the wrong format before it misinterprets anything. Failing it means one of:
- The wrong kind of file entirely. The most common version is an HTML page saved under a
.binname, from a download that hit a redirect, a login wall or a rate limit. Open the first line in a text viewer; if it starts with a tag, that is your answer. - A model for a different runtime. whisper.cpp uses its own ggml files, conventionally named
ggml-<size>.bin. OpenAI’s original PyTorch checkpoints, Core ML.mlmodelcbundles and OpenVINO IR files are all valid files that this loader cannot read, and pointing-mat one produces exactly this error. The Core ML and OpenVINO artefacts are companions to the ggml file, not replacements for it — you need both. - Git LFS pointer files. Cloning a repository without LFS installed leaves small text stubs where the weights should be. The size gives it away instantly.
The equivalent error in the llama.cpp family, where the message names the magic and version together, is covered in unknown magic and version combination.
Failure three: the tensors do not match
This is the version-skew case, and it is the one the search term usually means. The magic passed, the hyperparameters parsed, and then a tensor turned up that this build does not expect — a wrong name, a wrong element count, a wrong shape, or fewer tensors than the model declares.
It happens because the format and the model family both evolved. Whisper large has had multiple revisions, and the loader distinguishes them partly by structural properties — layer counts of 4, 6, 12, 24 and 32 correspond to tiny, base, small, medium and large, and the large variants are told apart by vocabulary size. A build that predates a model revision will parse the header, build the wrong expectation, and fail on the first tensor that disagrees. Quantized files add a second axis: invalid model (bad ftype value) means the file declares a weight type this build’s ggml does not know, which is again an age mismatch and not corruption.
The fix is to align the two ends, and the cheap direction is usually the binary: pull and rebuild whisper.cpp, because a newer build reads older files far more reliably than an older build reads newer ones.
The distinction between the three tensor complaints is worth keeping, because they point at different mismatches. A wrong shape means the loader built its expectation from the header and the file disagrees — a genuine architecture-revision skew. A wrong size with the right shape usually means a different weight type than expected, which is the quantization axis again. An unknown tensor name means the file contains something this build has no slot for, which is what a newer model against an older binary looks like. And not all tensors loaded means the file ran out before the model was complete, which is truncation rather than version skew and sends you back to the download.
One more source of this class of failure that is not skew at all: pointing -m at a quantized ggml file built by a fork, or at a file whose name says one size and whose contents are another. The published files follow a strict convention — ggml-base.en.bin, ggml-large-v3-turbo.bin, ggml-medium-q5_0.bin — and a renamed file is a common way to end up loading a model you did not intend. The loader tells you what it decided the model was; if that line disagrees with the filename, trust the loader.
Getting a model file that loads
- Check the file:
ls -lfor the size, and the first bytes for HTML or an LFS pointer. Anything implausible is a download problem, not a model problem. - Re-fetch with the repository’s own script, which knows the current names and locations:
bash ./models/download-ggml-model.sh base.en
- Update and rebuild the binary, so a file published after your checkout is understood:
git pull cmake -B build && cmake --build build --config Release -j
- Run with an absolute path and confirm the model type in the log. On success the loader prints the parsed hyperparameters, so you can see it recognised the size you intended:
./build/bin/whisper-cli -m "$PWD/models/ggml-base.en.bin" -f samples/jfk.wav
If the model loads and the transcript is the problem rather than the load, that is a separate matter — hallucinated text over silence is the most common one, and how Whisper works explains the segmentation behaviour behind it.