mudler/LocalAI · critical
voice-detect: dlopen %q: %w
Error message
voice-detect: dlopen %q: %w
What it means
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.
Source
Thrown at backend/go/voice-detect/main.go:36
var (
addr = flag.String("addr", "localhost:50051", "the address to connect to")
)
type LibFuncs struct {
FuncPtr any
Name string
}
func main() {
libName := os.Getenv("VOICEDETECT_LIBRARY")
if libName == "" {
libName = "libvoicedetect.so"
}
lib, err := purego.Dlopen(libName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
if err != nil {
panic(fmt.Errorf("voice-detect: dlopen %q: %w", libName, err))
}
// Bound 1:1 to voicedetect_capi.h. char*/float* returns are registered as
// uintptr so the raw pointer can be freed via the matching capi free fn.
libFuncs := []LibFuncs{
{&CppAbiVersion, "voicedetect_capi_abi_version"},
{&CppLoad, "voicedetect_capi_load"},
{&CppFree, "voicedetect_capi_free"},
{&CppLastError, "voicedetect_capi_last_error"},
{&CppFreeString, "voicedetect_capi_free_string"},
{&CppFreeVec, "voicedetect_capi_free_vec"},
{&CppEmbedPath, "voicedetect_capi_embed_path"},
{&CppEmbedPCM, "voicedetect_capi_embed_pcm"},
{&CppVerifyPaths, "voicedetect_capi_verify_paths"},
{&CppAnalyzeJSON, "voicedetect_capi_analyze_path_json"},
}
for _, lf := range libFuncs {
purego.RegisterLibFunc(lf.FuncPtr, lib, lf.Name)View on GitHub (pinned to 44413a9d06)
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
Example fix
# before ./voice-detect # panic: voice-detect: dlopen "libvoicedetect.so": ... # after VOICEDETECT_LIBRARY=/opt/localai/backends/libvoicedetect.so ./voice-detect
Defensive patterns
Strategy: validation
Validate before calling
lib := os.Getenv("VOICEDETECT_LIBRARY"); if lib == "" { lib = "libvoicedetect.so" }
if _, err := os.Stat(lib); err != nil { log.Fatalf("voice-detect: library %q missing: %v", lib, err) } Type guard
func libAvailable(path string) bool { _, err := os.Stat(path); return err == nil } Prevention
- Package the .so beside the backend binary
- Use absolute VOICEDETECT_LIBRARY paths in deployment configs
- ldd-audit the image during build
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- ced: dlopen %q: %w
- face-detect: dlopen %q: %w
- moss-transcribe-cpp: dlopen %q: %w
- parakeet-cpp: dlopen %q: %w
- trellis2 ABI mismatch: library reports %d, backend built for
AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15).
Data as JSON: /api/errors/894b90b7ae6c6d6d.
Report an issue: GitHub.