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

  1. Make library unload idempotent: track closed state and skip closeLibrary for nil/already-closed handles.
  2. Audit teardown paths for duplicate close calls (defer + explicit call).
  3. If unloading is not essential to your use case, log and continue — the OS reclaims the library at process exit.
  4. 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

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


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/8bd9ebf4de0c780f. Report an issue: GitHub.