{"record":{"id":"f42f41c4b63d0630","repo":"mudler/LocalAI","slug":"ced-dlopen-q-w","errorCode":null,"errorMessage":"ced: dlopen %q: %w","messagePattern":"ced: dlopen %q: %w","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"backend/go/ced/main.go","lineNumber":39,"sourceCode":"var addr = flag.String(\"addr\", \"localhost:50051\", \"the address to connect to\")\n\ntype libFunc struct {\n\tptr  any\n\tname string\n}\n\nfunc main() {\n\tlibName := os.Getenv(\"CED_LIBRARY\")\n\tif libName == \"\" {\n\t\tif runtime.GOOS == \"darwin\" {\n\t\t\tlibName = \"libced.dylib\"\n\t\t} else {\n\t\t\tlibName = \"libced.so\"\n\t\t}\n\t}\n\tlib, err := purego.Dlopen(libName, purego.RTLD_NOW|purego.RTLD_GLOBAL)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"ced: dlopen %q: %w\", libName, err))\n\t}\n\n\t// Bound 1:1 to ced_capi.h. char*-returning functions are declared uintptr\n\t// so we can free the same pointer with ced_capi_free_string after copying\n\t// (purego's string return would copy and leak the original).\n\tfor _, lf := range []libFunc{\n\t\t{&CppAbiVersion, \"ced_capi_abi_version\"},\n\t\t{&CppLoad, \"ced_capi_load\"},\n\t\t{&CppFree, \"ced_capi_free\"},\n\t\t{&CppLastError, \"ced_capi_last_error\"},\n\t\t{&CppNumClasses, \"ced_capi_num_classes\"},\n\t\t{&CppSampleRate, \"ced_capi_sample_rate\"},\n\t\t{&CppClassifyPathJSON, \"ced_capi_classify_path_json\"},\n\t\t{&CppClassifyPcmJSON, \"ced_capi_classify_pcm_json\"},\n\t\t{&CppFreeString, \"ced_capi_free_string\"},\n\t} {\n\t\tpurego.RegisterLibFunc(lf.ptr, lib, lf.name)\n\t}","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/backend/go/ced/main.go#L21-L57","documentation":"Startup panic of the Go ced backend process when purego.Dlopen cannot load the C++ ced shared library. The library name comes from the CED_LIBRARY env var, defaulting to libced.dylib on macOS and libced.so elsewhere. RTLD_NOW|RTLD_GLOBAL means all symbols must resolve and the lib must be findable via the normal dynamic linker search path.","triggerScenarios":"Starting the ced backend when libced.so was not built/installed, CED_LIBRARY points to a wrong path, the lib exists but a transitive dependency (OpenCV, ONNX Runtime, etc.) is missing, or an arm64/x86_64 architecture mismatch exists between the Go binary and the .so.","commonSituations":"Running a manually built core binary without running the backend's build step; container images missing runtime libs; copying a library built on another distro with a different glibc; forgetting to export CED_LIBRARY when the lib is in a nonstandard directory.","solutions":["Verify the library exists: ls -l $CED_LIBRARY or ./libced.so in the backend working directory","Rebuild the C++ side of the backend (see the ced backend's build script/Dockerfile) so the .so is produced next to the binary","Set CED_LIBRARY to the absolute path of the library and re-run","Diagnose missing transitive deps with ldd libced.so (Linux) or otool -L libced.dylib (macOS) and install them","Confirm architecture match with file libced.so vs the Go binary"],"exampleFix":"# before\n./ced  # panic: ced: dlopen \"libced.so\": ... \n# after\nCED_LIBRARY=/opt/localai/lib/libced.so ./ced","handlingStrategy":"validation","validationCode":"lib := os.Getenv(\"CED_LIBRARY\"); if lib == \"\" { lib = \"libced.so\" }\nif _, err := os.Stat(lib); errors.Is(err, fs.ErrNotExist) {\n    lib = resolveBuiltArtifact() // or fail fast with a clear message\n}","typeGuard":"func libAvailable(path string) bool { _, err := os.Stat(path); return err == nil }","tryCatchPattern":"// panic in main cannot be caught; guard before Dlopen\nif err := checkDeps(libName); err != nil { log.Fatalf(\"ced: preload check: %v\", err) }","preventionTips":["Run ldd on the .so in the deploy image as a CI step","Set CED_LIBRARY to an absolute path in service units","Build the native lib and Go backend from the same commit"],"tags":["dlopen","native-library","go","backend","environment"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}