mudler/LocalAI · critical
face-detect: dlopen %q: %w
Error message
face-detect: dlopen %q: %w
What it means
Startup panic of the Go face-detect backend when purego.Dlopen fails to load libfacedetect.so. The path comes from FACEDETECT_LIBRARY, defaulting to libfacedetect.so in the current search path. Because the backend binds every facedetect_capi_* symbol through purego, both load failure and later symbol resolution problems stem from the same .so.
Source
Thrown at backend/go/face-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("FACEDETECT_LIBRARY")
if libName == "" {
libName = "libfacedetect.so"
}
lib, err := purego.Dlopen(libName, purego.RTLD_NOW|purego.RTLD_GLOBAL)
if err != nil {
panic(fmt.Errorf("face-detect: dlopen %q: %w", libName, err))
}
// Bound 1:1 to facedetect_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, "facedetect_capi_abi_version"},
{&CppLoad, "facedetect_capi_load"},
{&CppFree, "facedetect_capi_free"},
{&CppLastError, "facedetect_capi_last_error"},
{&CppFreeString, "facedetect_capi_free_string"},
{&CppFreeVec, "facedetect_capi_free_vec"},
{&CppEmbedPath, "facedetect_capi_embed_path"},
{&CppEmbedRGB, "facedetect_capi_embed_rgb"},
{&CppDetectJSON, "facedetect_capi_detect_path_json"},
{&CppVerifyPaths, "facedetect_capi_verify_paths"},
{&CppAnalyzeJSON, "facedetect_capi_analyze_path_json"},
}
for _, lf := range libFuncs {View on GitHub (pinned to 44413a9d06)
Solutions
- Check the file at $FACEDETECT_LIBRARY (or ./libfacedetect.so) exists and is readable
- Build the native library per the backend's build instructions and place it beside the backend binary
- Export FACEDETECT_LIBRARY=/absolute/path/to/libfacedetect.so
- Run ldd on the .so and install any reported missing shared libraries
Example fix
# before ./face-detect # panic: face-detect: dlopen "libfacedetect.so": ... # after FACEDETECT_LIBRARY=/opt/localai/backends/libfacedetect.so ./face-detect
Defensive patterns
Strategy: validation
Validate before calling
lib := os.Getenv("FACEDETECT_LIBRARY"); if lib == "" { lib = "libfacedetect.so" }
if _, err := os.Stat(lib); err != nil { log.Fatalf("face-detect: library %q missing: %v", lib, err) } Type guard
func libAvailable(path string) bool { _, err := os.Stat(path); return err == nil } Prevention
- Ship the .so with the backend binary in the same artifact
- Verify FACEDETECT_LIBRARY in the environment of the service, not just your shell
- Add a container healthcheck that stats the library before marking the backend ready
When it happens
Trigger: Launching the face-detect backend without the compiled libfacedetect.so on the loader path, with FACEDETECT_LIBRARY set to a nonexistent file, or with the .so present but built against unavailable shared dependencies.
Common situations: Missing build step for the C++ detector; deploying only the Go binary to a host without the native lib; FACEDETECT_LIBRARY stale after a reinstall moved the lib; CPU-only image lacking SIMD-capable build of the dependency.
Related errors
- ced: dlopen %q: %w
- moss-transcribe-cpp: dlopen %q: %w
- parakeet-cpp: dlopen %q: %w
- voice-detect: 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/d328e43ab46458e2.
Report an issue: GitHub.