BoundaryML/baml · error
dlclose failed
Error message
dlclose failed
What it means
This is the fallback message returned by closeLibrary when dlclose() fails but dlerror() returns an empty string, so no OS detail is available. Like the detailed variant, it means the BAML native shared library handle could not be unloaded on Unix. The absence of a detail string makes a stale/invalid handle the most likely cause.
Source
Thrown at engine/language_client_go/baml_go/lib_unix.go:82
} else {
errMsg += ": symbol not found"
}
return nil, fmt.Errorf("%s", errMsg)
}
return symbol, nil
}
// closeLibrary closes the loaded library
func closeLibrary(handle unsafe.Pointer) error {
if handle == nil {
return nil
}
if C.dlclose(handle) != 0 {
errStr := C.GoString(C.dlerror())
if errStr != "" {
return fmt.Errorf("dlclose failed: %s", errStr)
}
return fmt.Errorf("dlclose failed")
}
return nil
}
// platformInit performs any platform-specific initialization
func platformInit() error {
// Unix doesn't need special initialization
return nil
}View on GitHub (pinned to bd85ce9dee)
Solutions
- Make library unload idempotent: track closed state and skip closeLibrary for nil/already-closed handles.
- Audit teardown paths for duplicate close calls (defer + explicit call).
- If unloading is not essential to your use case, log and continue — the OS reclaims the library at process exit.
- Update the baml Go bindings/native library if a linker quirk in your platform build is suspected.
Example fix
// before
defer closeLibrary(handle)
// ...
closeLibrary(handle) // second close -> "dlclose failed"
// after
defer func() {
if handle != nil {
_ = closeLibrary(handle)
handle = nil
}
}() Defensive patterns
Strategy: try-catch
Validate before calling
if handle == nil || alreadyClosed {
return nil
} Type guard
func closable(h unsafe.Pointer, closed bool) bool {
return h != nil && !closed
} Try / catch
if err := closeLibrary(handle); err != nil {
log.Printf("library unload skipped: %v", err)
} Prevention
- Centralize library load/unload in one component; never close from multiple call sites.
- Avoid unloading during tests; load once per process.
- Log the error but rely on process exit to reclaim the library.
When it happens
Trigger: closeLibrary invoked with a handle for which C.dlclose returns nonzero and C.dlerror() yields no message — typically a handle that was already closed or was never validly produced by dlopen.
Common situations: Teardown code that runs twice (e.g. via defer plus explicit close); process shutdown hooks racing with each other; embedded environments where dlclose cannot actually unload due to symbol references still being held.
Related errors
- dlclose failed: %s
- FreeLibrary failed: %w
- failed to exec baml-cli: {err}
- failed to exec {}: {err}{origin}
- toolchain binary is not executable: {}{origin}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/8bd9ebf4de0c780f.
Report an issue: GitHub.