{"record":{"id":"26c3769f5e41cf43","repo":"mudler/LocalAI","slug":"trellis2-abi-mismatch-library-reports-d-backend","errorCode":null,"errorMessage":"trellis2 ABI mismatch: library reports %d, backend built for %d","messagePattern":"trellis2 ABI mismatch: library reports (.+?), backend built for (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"backend/go/trellis2cpp/main.go","lineNumber":42,"sourceCode":"\t// run.sh selects the CPU-variant directory and points TRELLIS2_LIBRARY at it.\n\tlibName := os.Getenv(\"TRELLIS2_LIBRARY\")\n\tif libName == \"\" {\n\t\tif runtime.GOOS == \"darwin\" {\n\t\t\tlibName = \"./variants/fallback/libtrellis2.dylib\"\n\t\t} else {\n\t\t\tlibName = \"./variants/fallback/libtrellis2.so\"\n\t\t}\n\t}\n\n\tlib, err := purego.Dlopen(libName, purego.RTLD_NOW|purego.RTLD_GLOBAL)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tregisterLibFuncs(lib)\n\n\tif got := t2AbiVersion(); got != abiVersion {\n\t\tpanic(fmt.Sprintf(\"trellis2 ABI mismatch: library reports %d, backend built for %d\", got, abiVersion))\n\t}\n\n\tflag.Parse()\n\n\tif err := grpc.StartServer(*addr, &Trellis2{}); err != nil {\n\t\tpanic(err)\n\t}\n}\n","sourceCodeStart":24,"sourceCodeEnd":51,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/backend/go/trellis2cpp/main.go#L24-L51","documentation":"Startup panic of the Go trellis2 backend: after dlopen of the trellis2 library succeeds, the C API's reported ced-style ABI version (t2AbiVersion()) does not equal the abiVersion constant the Go binary was compiled against. This guard exists because purego has no compile-time type checking — a mismatched struct layout would cause memory corruption, so the backend refuses to start.","triggerScenarios":"Mixing a Go trellis2cpp binary built against one version of trellis2_capi.h with a libtrellis2.so built from another (e.g. after a partial upgrade, or picking up a stale ./variants/fallback/libtrellis2.so).","commonSituations":"Upgrading LocalAI core without rebuilding backends; CI caching the Go binary but rebuilding the C++ lib (or vice versa); a downstream packager shipping mismatched lib/binary pairs; switching between CUDA and fallback variants built at different revisions.","solutions":["Rebuild the trellis2 native library and the Go backend from the same source revision so the ABI constant matches","Remove stale variants/fallback/libtrellis2.so copies that shadow the fresh build","Check backend release notes/changelog for ABI-breaking changes and update both components together","If vendoring, pin both the lib and the Go module to the same release tag"],"exampleFix":"# before: stale lib shadowing fresh build\nls ./variants/fallback/libtrellis2.so  # old ABI\n# after\ngit pull && make -C backend rebuild-trellis2 && rm ./variants/fallback/libtrellis2.so","handlingStrategy":"validation","validationCode":"// before starting the server, verify the ABI matches\nlib, err := purego.Dlopen(libName, purego.RTLD_NOW|purego.RTLD_GLOBAL)\nif err != nil { log.Fatal(err) }\n// bind t2AbiVersion and compare to your compiled-in abiVersion first","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat Go backend and native lib as one versioned unit; build and ship them together","In CI, start the backend once as a smoke test to catch ABI mismatch before release","Delete stale variants/fallback libs after rebuilding"],"tags":["abi","version-skew","native-library","go","backend"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}