{"record":{"id":"3d7b20c56069a61c","repo":"BoundaryML/baml","slug":"invalid-symbol-name-w","errorCode":null,"errorMessage":"invalid symbol name: %w","messagePattern":"invalid symbol name: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/language_client_go/baml_go/lib_windows.go","lineNumber":49,"sourceCode":"\tpathPtr, err := syscall.UTF16PtrFromString(path)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid library path: %w\", err)\n\t}\n\n\thandle, _, err := procLoadLibraryW.Call(uintptr(unsafe.Pointer(pathPtr)))\n\tif handle == 0 {\n\t\tlastErr, _, _ := procGetLastError.Call()\n\t\treturn nil, fmt.Errorf(\"LoadLibrary failed for %s: error code %d: %w\", path, lastErr, err)\n\t}\n\n\treturn unsafe.Pointer(handle), nil\n}\n\n// getSymbol retrieves a symbol from the loaded library\nfunc getSymbol(handle unsafe.Pointer, name string) (unsafe.Pointer, error) {\n\tnamePtr, err := syscall.BytePtrFromString(name)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid symbol name: %w\", err)\n\t}\n\n\tproc, _, err := procGetProcAddress.Call(\n\t\tuintptr(handle),\n\t\tuintptr(unsafe.Pointer(namePtr)),\n\t)\n\n\tif proc == 0 {\n\t\tlastErr, _, _ := procGetLastError.Call()\n\t\treturn nil, fmt.Errorf(\"GetProcAddress failed for %s: error code %d: %w\", name, lastErr, err)\n\t}\n\n\treturn unsafe.Pointer(proc), nil\n}\n\n// closeLibrary closes the loaded library\nfunc closeLibrary(handle unsafe.Pointer) error {\n\tif handle == nil {","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_go/baml_go/lib_windows.go#L31-L67","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nproc := getSymbol(handle, rawNameFromBuffer) // \"baml_fn\\x00\"\n\n// after\nname := strings.TrimRight(rawNameFromBuffer, \"\\x00\")\nif strings.ContainsRune(name, 0) {\n    return fmt.Errorf(\"invalid symbol name %q\", name)\n}\nproc := getSymbol(handle, name)","handlingStrategy":"validation","validationCode":"if strings.ContainsRune(name, 0) {\n    return fmt.Errorf(\"symbol name contains NUL byte: %q\", name)\n}","typeGuard":"func validSymbolName(n string) bool {\n    return n != \"\" && !strings.ContainsRune(n, 0)\n}","tryCatchPattern":"if _, err := syscall.BytePtrFromString(name); err != nil {\n    return fmt.Errorf(\"bad symbol name: %w\", err)\n}","preventionTips":["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."],"tags":["windows","dynamic-linking","string-validation"],"backgroundTag":"invalid-argument-format","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}