BoundaryML/baml · error
invalid symbol name: %w
Error message
invalid symbol name: %w
What it means
getSymbol on Windows converts the symbol name to a byte pointer with syscall.BytePtrFromString before calling GetProcAddress. This error means that conversion failed, which occurs only when the symbol name contains a NUL byte. Since symbol names are typically literals in the BAML bindings, this almost always indicates a programmatic construction of the name from a raw buffer.
Source
Thrown at engine/language_client_go/baml_go/lib_windows.go:49
pathPtr, err := syscall.UTF16PtrFromString(path)
if err != nil {
return nil, fmt.Errorf("invalid library path: %w", err)
}
handle, _, err := procLoadLibraryW.Call(uintptr(unsafe.Pointer(pathPtr)))
if handle == 0 {
lastErr, _, _ := procGetLastError.Call()
return nil, fmt.Errorf("LoadLibrary failed for %s: error code %d: %w", path, lastErr, err)
}
return unsafe.Pointer(handle), nil
}
// getSymbol retrieves a symbol from the loaded library
func getSymbol(handle unsafe.Pointer, name string) (unsafe.Pointer, error) {
namePtr, err := syscall.BytePtrFromString(name)
if err != nil {
return nil, fmt.Errorf("invalid symbol name: %w", err)
}
proc, _, err := procGetProcAddress.Call(
uintptr(handle),
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 {View on GitHub (pinned to bd85ce9dee)
Solutions
- Trim NUL bytes from the name before lookup: strings.TrimRight(name, "\x00").
- Use static symbol-name literals instead of deriving names from buffers where possible.
- Add a validation check strings.ContainsRune(name, 0) before calling the runtime lookup.
- If names come from a data file, fix the generator to strip terminators at the source.
Example fix
// before
proc := getSymbol(handle, rawNameFromBuffer) // "baml_fn\x00"
// after
name := strings.TrimRight(rawNameFromBuffer, "\x00")
if strings.ContainsRune(name, 0) {
return fmt.Errorf("invalid symbol name %q", name)
}
proc := getSymbol(handle, name) Defensive patterns
Strategy: validation
Validate before calling
if strings.ContainsRune(name, 0) {
return fmt.Errorf("symbol name contains NUL byte: %q", name)
} Type guard
func validSymbolName(n string) bool {
return n != "" && !strings.ContainsRune(n, 0)
} Try / catch
if _, err := syscall.BytePtrFromString(name); err != nil {
return fmt.Errorf("bad symbol name: %w", err)
} Prevention
- Use static symbol-name literals instead of names derived from binary data.
- Trim trailing NUL bytes when names are read from buffers.
- Keep a whitelist of known symbol names to look up.
When it happens
Trigger: getSymbol called with a name string containing an embedded NUL character, e.g. a symbol name sliced from a C buffer or built with byte concatenation without trimming the terminator.
Common situations: Introspection/dynamic-binding code that reads symbol names from binary data; string truncation bugs where the trailing 0x00 is retained; corrupted lookup tables of exported symbol names.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid library path: %w
- LoadLibrary failed for %s: error code %d: %w
- GetProcAddress failed for %s: error code %d: %w
- FreeLibrary failed: %w
- usage: baml --replace <tmp> <current>
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/3d7b20c56069a61c.
Report an issue: GitHub.