BoundaryML/baml · error

%s

Error message

%s

What it means

After a failed C.dlsym lookup, getSymbol builds a message "dlsym error for <name>[: <dlerror> | : symbol not found]" and returns it via fmt.Errorf("%s", ...). It means the requested exported symbol does not exist in the loaded native library (or version mismatch changed its name).

Source

Thrown at engine/language_client_go/baml_go/lib_unix.go:67

	if handle == nil {
		return nil, fmt.Errorf("library handle is nil when looking up symbol '%s'", name)
	}

	cName := C.CString(name)
	defer C.free(unsafe.Pointer(cName))

	C.dlerror() // Clear any existing error
	symbol := C.dlsym(handle, cName)
	errStr := C.GoString(C.dlerror())

	if symbol == nil {
		errMsg := fmt.Sprintf("dlsym error for %s", name)
		if errStr != "" {
			errMsg += fmt.Sprintf(": %s", errStr)
		} 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
}

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Re-download/reinstall the native library so its version matches the Go bindings
  2. Verify the symbol exists: `nm -D <path> | grep <name>` (or `nm -gU` on macOS)
  3. Clear stale cached library versions and pin matching versions of the client package and native artifact
  4. Check the appended dlerror detail for loader-level problems (relocations, dependency symbols)

Example fix

// before
nm -D ~/.cache/baml/native/libbaml.so | grep baml_fn  -> not found (v0.51 lib with v0.55 bindings)
// after
go get github.com/boundaryml/baml/go@v0.51  # align bindings with cached lib
# or clear cache so the matching native lib is re-downloaded
Defensive patterns

Strategy: try-catch

Validate before calling

out, err := exec.Command("nm", "-D", libPath).Output()
if err != nil || !strings.Contains(string(out), symbolName) {
    return fmt.Errorf("symbol %s absent from %s; version mismatch?", symbolName, libPath)
}

Try / catch

sym, err := getSymbol(handle, name)
if err != nil && strings.Contains(err.Error(), "dlsym error for") {
    // artifact/bindings mismatch: refresh the native library to match client version
    return refreshLibraryAndRetry(handle, name)
}

Prevention

When it happens

Trigger: dlsym(handle, name) returns nil with a non-empty dlerror string, or returns nil with empty error — symbol absent from the shared library.

Common situations: Go bindings version out of sync with the downloaded native library (renamed/removed exports); loading an old cached .so with newer client code; stripped binaries missing exported symbols.

Related errors


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