{"record":{"id":"894b90b7ae6c6d6d","repo":"mudler/LocalAI","slug":"voice-detect-dlopen-q-w","errorCode":null,"errorMessage":"voice-detect: dlopen %q: %w","messagePattern":"voice-detect: dlopen %q: %w","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"backend/go/voice-detect/main.go","lineNumber":36,"sourceCode":"\nvar (\n\taddr = flag.String(\"addr\", \"localhost:50051\", \"the address to connect to\")\n)\n\ntype LibFuncs struct {\n\tFuncPtr any\n\tName    string\n}\n\nfunc main() {\n\tlibName := os.Getenv(\"VOICEDETECT_LIBRARY\")\n\tif libName == \"\" {\n\t\tlibName = \"libvoicedetect.so\"\n\t}\n\n\tlib, err := purego.Dlopen(libName, purego.RTLD_NOW|purego.RTLD_GLOBAL)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"voice-detect: dlopen %q: %w\", libName, err))\n\t}\n\n\t// Bound 1:1 to voicedetect_capi.h. char*/float* returns are registered as\n\t// uintptr so the raw pointer can be freed via the matching capi free fn.\n\tlibFuncs := []LibFuncs{\n\t\t{&CppAbiVersion, \"voicedetect_capi_abi_version\"},\n\t\t{&CppLoad, \"voicedetect_capi_load\"},\n\t\t{&CppFree, \"voicedetect_capi_free\"},\n\t\t{&CppLastError, \"voicedetect_capi_last_error\"},\n\t\t{&CppFreeString, \"voicedetect_capi_free_string\"},\n\t\t{&CppFreeVec, \"voicedetect_capi_free_vec\"},\n\t\t{&CppEmbedPath, \"voicedetect_capi_embed_path\"},\n\t\t{&CppEmbedPCM, \"voicedetect_capi_embed_pcm\"},\n\t\t{&CppVerifyPaths, \"voicedetect_capi_verify_paths\"},\n\t\t{&CppAnalyzeJSON, \"voicedetect_capi_analyze_path_json\"},\n\t}\n\tfor _, lf := range libFuncs {\n\t\tpurego.RegisterLibFunc(lf.FuncPtr, lib, lf.Name)","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/backend/go/voice-detect/main.go#L18-L54","documentation":"Startup panic of the Go voice-detect backend when purego.Dlopen fails to load libvoicedetect.so. The path comes from VOICEDETECT_LIBRARY, defaulting to libvoicedetect.so. The backend subsequently registers all voicedetect_capi_* functions, so the library must be the exact build the binary expects.","triggerScenarios":"Starting voice-detect without the compiled libvoicedetect.so reachable by the dynamic linker; VOICEDETECT_LIBRARY pointing to a missing/moved file; the .so failing RTLD_NOW due to unresolved symbols or absent transitive dependencies.","commonSituations":"Deploying the Go binary alone; the library living outside the default search path without the env var set; glibc/ffmpeg version differences between build and run hosts; permissions issues on the mounted artifacts volume.","solutions":["Confirm libvoicedetect.so exists where the process looks (cwd or $VOICEDETECT_LIBRARY)","Build the native library per the backend's build docs and place it beside the binary","Export VOICEDETECT_LIBRARY with the absolute path","Inspect with ldd libvoicedetect.so and install missing dependencies"],"exampleFix":"# before\n./voice-detect  # panic: voice-detect: dlopen \"libvoicedetect.so\": ...\n# after\nVOICEDETECT_LIBRARY=/opt/localai/backends/libvoicedetect.so ./voice-detect","handlingStrategy":"validation","validationCode":"lib := os.Getenv(\"VOICEDETECT_LIBRARY\"); if lib == \"\" { lib = \"libvoicedetect.so\" }\nif _, err := os.Stat(lib); err != nil { log.Fatalf(\"voice-detect: library %q missing: %v\", lib, err) }","typeGuard":"func libAvailable(path string) bool { _, err := os.Stat(path); return err == nil }","tryCatchPattern":null,"preventionTips":["Package the .so beside the backend binary","Use absolute VOICEDETECT_LIBRARY paths in deployment configs","ldd-audit the image during build"],"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"}