Skip to content

[Bug]: WinError 127 loading ggml-base.dll on Windows: bundled libomp140.x86_64.dll is shadowed by a stale copy in System32 #156

Description

@ycao17

WinError 127 loading ggml-base.dll on Windows: bundled libomp140.x86_64.dll is shadowed by a stale copy in System32

Summary

On Windows, import llama_cpp fails with WinError 127 (the specified procedure could not be found) if an older libomp140.x86_64.dll exists in C:\Windows\System32. The wheel ships a compatible libomp140.x86_64.dll right next to ggml-base.dll, but the loader never looks there, so the stale System32 copy wins.

Preloading the bundled DLL by absolute path before importing llama_cpp fixes it completely.

Environment

  • Windows 11 x64
  • Python 3.13.12 (venv, ComfyUI Desktop)
  • llama_cpp_python-0.3.43+cu131-cp313-cp313-win_amd64.whl
  • Previously working: 0.3.33 from the same source

Error

RuntimeError: Failed to load 'ggml-base' from [.../llama_cpp/lib, .../llama_cpp/bin]
.../llama_cpp/lib/ggml-base.dll: [WinError 127] The specified procedure could not be found.
.../llama_cpp/bin/ggml-base.dll: [WinError 127] The specified procedure could not be found.

Raised from _ctypes_extensions.py:167, via _ggml.py:30.

Note this is error 127, not 126 — the DLL and all of its dependencies were found. One of them was missing an expected export.

Diagnosis

ggml-base.dll imports from libomp140.x86_64.dll. Two copies exist:

Location SHA256 (truncated)
C:\WINDOWS\SYSTEM32\libomp140.x86_64.dll 48107D29…
site-packages\llama_cpp\lib\libomp140.x86_64.dll 9AB1CB78…

Different binaries. Note that both report FileVersion 20140926 — LLVM hardcodes that string regardless of release, so version comparison is useless here and actively misleading.

Checking every symbol ggml-base.dll imports against the export table of the bundled copy:

llama_cpp/lib/libomp140.x86_64.dll   needs 7, missing 0
llama_cpp/lib/msvcp140.dll           needs 4, missing 0
llama_cpp/lib/vcruntime140.dll       needs 11, missing 0

The bundled DLLs satisfy ggml-base.dll completely. The wheel is fine — the problem is purely which copy Windows resolves to.

Confirming which file actually gets loaded:

libomp140.x86_64.dll  ->  C:\WINDOWS\SYSTEM32\libomp140.x86_64.dll

Why the bundled copy loses

Under LoadLibraryExW with no altered-search flags, the search order includes the application directory (python.exe's folder), System32, the Windows directory, and PATH — but not the directory of the DLL being loaded. So when ggml-base.dll resolves its libomp140.x86_64.dll import, llama_cpp/lib is never consulted, even though the file sits right beside it.

Consistent with this: os.add_dll_directory(<llama_cpp/lib>) does not fix the failure, because user directories added that way are only searched when LOAD_LIBRARY_SEARCH_USER_DIRS / LOAD_LIBRARY_SEARCH_DEFAULT_DIRS is in effect.

Workaround

Preloading the bundled libomp by absolute path — which puts a module with that base name in the process, so the loader reuses it instead of searching — resolves it immediately:

import ctypes
ctypes.WinDLL(r"...\site-packages\llama_cpp\lib\libomp140.x86_64.dll")
from llama_cpp.llama_chat_format import Qwen3VLChatHandler   # now succeeds

I've made this permanent with a .pth file in site-packages that resolves the path via importlib.util.find_spec("llama_cpp"), so it survives reinstalls.

Suggested fix

In _ggml.py, preload the bundled dependencies from the package directory before loading ggml-base:

import ctypes, os

for _dep in ("libomp140.x86_64.dll",):
    for _dir in _base_paths:
        _p = os.path.join(_dir, _dep)
        if os.path.exists(_p):
            try:
                ctypes.WinDLL(_p)
            except OSError:
                pass
            break

Alternatively, load ggml-base.dll with winmode=0x00000008 (LOAD_WITH_ALTERED_SEARCH_PATH), which makes the loader treat the DLL's own directory as the search root for its dependencies — though explicit preloading is more predictable.

Either way, the bundled DLLs would then win over whatever happens to be in System32.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions