BoundaryML/baml · error
FreeLibrary failed: %w
Error message
FreeLibrary failed: %w
What it means
closeLibrary on Windows returns this error when FreeLibrary returns 0, meaning Windows could not decrement the DLL's reference count / unload the BAML native library. It wraps the syscall error. As with dlclose failures, this usually means the handle was invalid or already freed rather than a configuration problem.
Source
Thrown at engine/language_client_go/baml_go/lib_windows.go:72
uintptr(unsafe.Pointer(namePtr)),
)
if proc == 0 {
lastErr, _, _ := procGetLastError.Call()
return nil, fmt.Errorf("GetProcAddress failed for %s: error code %d: %w", name, lastErr, err)
}
return unsafe.Pointer(proc), nil
}
// closeLibrary closes the loaded library
func closeLibrary(handle unsafe.Pointer) error {
if handle == nil {
return nil
}
ret, _, err := procFreeLibrary.Call(uintptr(handle))
if ret == 0 {
return fmt.Errorf("FreeLibrary failed: %w", err)
}
return nil
}
// platformInit performs any platform-specific initialization
func platformInit() error {
// Windows doesn't need special initialization
return nil
}View on GitHub (pinned to bd85ce9dee)
Solutions
- Ensure single ownership of the library handle: free it exactly once (sync.Once) and nil the reference after freeing.
- Wait for all goroutines using the BAML runtime to finish before closing the library.
- Inspect the wrapped syscall error for the underlying Win32 code and address it (e.g. handle validity).
- If unloading is not required, skip closeLibrary and let process exit release the DLL.
Example fix
// before
func shutdown() {
closeLibrary(handle)
}
// shutdown() called from two places -> FreeLibrary failed
// after
var freeOnce sync.Once
func shutdown() {
freeOnce.Do(func() {
if err := closeLibrary(handle); err != nil {
log.Printf("FreeLibrary warning: %v", err)
}
handle = nil
})
} Defensive patterns
Strategy: try-catch
Validate before calling
if handle == nil || freed {
return nil
} Type guard
func freeable(h unsafe.Pointer, freed bool) bool {
return h != nil && !freed
} Try / catch
if err := closeLibrary(handle); err != nil {
log.Printf("FreeLibrary warning (DLL released at process exit): %v", err)
} Prevention
- Free the DLL exactly once via sync.Once; nil the handle afterwards.
- Join all goroutines using the runtime before unloading.
- Skip explicit unload if the process is about to exit.
When it happens
Trigger: closeLibrary called with an invalid or already-freed handle; double-close in teardown paths; FreeLibrary failing because the DLL is still in use (loaded modules referencing it, active threads executing its code).
Common situations: Application shutdown hooks calling close twice; goroutines still running BAML calls while the library is being unloaded; handles copied and freed from multiple code paths.
Related errors
- LoadLibrary failed for %s: error code %d: %w
- GetProcAddress failed for %s: error code %d: %w
- dlclose failed: %s
- dlclose failed
- invalid library path: %w
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/ef8cfe83ac160f6d.
Report an issue: GitHub.