mudler/LocalAI · critical

moss-transcribe-cpp: dlopen %q: %w

Error message

moss-transcribe-cpp: dlopen %q: %w

What it means

Startup panic of the Go moss-transcribe-cpp backend when purego.Dlopen cannot load the Moss transcription library. Name comes from MOSS_TRANSCRIBE_LIBRARY, defaulting to libmoss-transcribe.dylib (macOS) or libmoss-transcribe.so (Linux). Loaded with RTLD_NOW so unresolved symbols also surface here as a dlopen error.

Source

Thrown at backend/go/moss-transcribe-cpp/main.go:42

type LibFuncs struct {
	FuncPtr any
	Name    string
}

func main() {
	libName := os.Getenv("MOSS_TRANSCRIBE_LIBRARY")
	if libName == "" {
		if runtime.GOOS == "darwin" {
			libName = "libmoss-transcribe.dylib"
		} else {
			libName = "libmoss-transcribe.so"
		}
	}

	lib, err := purego.Dlopen(libName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
	if err != nil {
		panic(fmt.Errorf("moss-transcribe-cpp: dlopen %q: %w", libName, err))
	}

	// Bound 1:1 to moss_transcribe_capi.h. The transcribe_* entry points return
	// a malloc'd char* the caller owns; we register those as uintptr so we get
	// the raw pointer back and can call moss_transcribe_capi_free_string on it
	// (purego's string return would copy and forget the original pointer,
	// leaking it on every call).
	libFuncs := []LibFuncs{
		{&CppAbiVersion, "moss_transcribe_capi_abi_version"},
		{&CppLoad, "moss_transcribe_capi_load"},
		{&CppFree, "moss_transcribe_capi_free"},
		{&CppTranscribePath, "moss_transcribe_capi_transcribe_path"},
		{&CppTranscribePcm, "moss_transcribe_capi_transcribe_pcm"},
		{&CppFreeString, "moss_transcribe_capi_free_string"},
		{&CppLastError, "moss_transcribe_capi_last_error"},
	}
	for _, lf := range libFuncs {
		purego.RegisterLibFunc(lf.FuncPtr, lib, lf.Name)

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Confirm the library file exists at the resolved path (check MOSS_TRANSCRIBE_LIBRARY and the platform default name)
  2. Rebuild libmoss-transcribe from the backend's build recipe on the target host
  3. Point MOSS_TRANSCRIBE_LIBRARY at the absolute path of the freshly built library
  4. Use ldd/otool -L to find and install missing transitive dependencies

Example fix

# before
./moss-transcribe-cpp  # panic: moss-transcribe-cpp: dlopen "libmoss-transcribe.so": ...
# after
MOSS_TRANSCRIBE_LIBRARY=/opt/localai/backends/libmoss-transcribe.so ./moss-transcribe-cpp
Defensive patterns

Strategy: validation

Validate before calling

lib := os.Getenv("MOSS_TRANSCRIBE_LIBRARY"); if lib == "" { lib = defaultLibName() }
if _, err := os.Stat(lib); err != nil { log.Fatalf("moss-transcribe-cpp: library %q missing: %v", lib, err) }

Type guard

func libAvailable(path string) bool { _, err := os.Stat(path); return err == nil }

Prevention

When it happens

Trigger: Starting moss-transcribe-cpp with the native lib missing from the loader path, MOSS_TRANSCRIBE_LIBRARY pointing at a stale or wrong-architecture build, or the .so's own dependencies (whisper/ffmpeg etc.) unavailable at runtime.

Common situations: Skipping the C++ build step; running on a host with older glibc than the build machine; mixed arm64/amd64 binaries copied between machines; env var set in a wrapper script that is not propagated to the service unit.

Related errors


AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15). Data as JSON: /api/errors/6f962b691f4374d7. Report an issue: GitHub.