{"record":{"id":"44059a8fc7f8c767","repo":"router-for-me/CLIProxyAPI","slug":"plugin-abi-version-d-is-not-supported-44059a","errorCode":null,"errorMessage":"plugin ABI version %d is not supported","messagePattern":"plugin ABI version (.+?) is not supported","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pluginhost/loader_windows.go","lineNumber":109,"sourceCode":"\tclient := &dynamicLibraryClient{\n\t\tdll:      dll,\n\t\ttempPath: loadPath,\n\t\thostCtx:  hostCtx,\n\t\thostAPI: &windowsHostAPI{\n\t\t\tabiVersion: pluginHostABIVersion,\n\t\t\thostCtx:    uintptr(unsafe.Pointer(hostCtx)),\n\t\t\tcall:       windowsHostCallCallback,\n\t\t\tfreeBuffer: windowsHostFreeCallback,\n\t\t},\n\t}\n\trc, _, errCall := proc.Call(uintptr(unsafe.Pointer(client.hostAPI)), uintptr(unsafe.Pointer(&client.api)))\n\tif rc != 0 {\n\t\tclient.closeAfterOpenFailure()\n\t\treturn nil, fmt.Errorf(\"cliproxy_plugin_init returned %d: %v\", rc, errCall)\n\t}\n\tif client.api.abiVersion != pluginHostABIVersion {\n\t\tclient.closeAfterOpenFailure()\n\t\treturn nil, fmt.Errorf(\"plugin ABI version %d is not supported\", client.api.abiVersion)\n\t}\n\tif client.api.call == 0 || client.api.freeBuffer == 0 {\n\t\tclient.closeAfterOpenFailure()\n\t\treturn nil, fmt.Errorf(\"plugin function table is incomplete\")\n\t}\n\treturn client, nil\n}\n\nfunc shadowCopyPlugin(file pluginFile) (string, error) {\n\tdir, errDir := shadowPluginDir()\n\tif errDir != nil {\n\t\treturn \"\", errDir\n\t}\n\tshadowPluginCleanupOnce.Do(func() {\n\t\tremoveStaleShadowPlugins(dir)\n\t})\n\treturn shadowCopyPluginToDir(file, dir)\n}","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/pluginhost/loader_windows.go#L91-L127","documentation":"After a successful cliproxy_plugin_init call on Windows, the plugin-filled API struct reports an abiVersion different from the host's pluginHostABIVersion. The host only speaks one ABI, so it refuses the plugin and closes it. This protects against struct-layout and calling-convention mismatches.","triggerScenarios":"Plugin compiled against an older or newer version of the pluginhost SDK whose pluginHostABIVersion constant differs; hand-written plugin that forgets to set api.abiVersion; plugin ABI struct layout changed between versions.","commonSituations":"Upgrading CLIProxyAPI without rebuilding third-party plugins; mixing plugin builds from a different release channel; vendored SDK copy in the plugin drifting from the host.","solutions":["Rebuild the plugin from source against the exact pluginhost SDK version shipped with the running server","If you maintain the plugin, verify it copies pluginHostABIVersion from the current SDK headers/module rather than hardcoding a number","Check the release notes of the server for plugin ABI bumps and obtain matching plugin builds"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"ABI version\") {\n    log.Error(\"plugin/host ABI mismatch: rebuild plugin against the running server's SDK version\")\n}","preventionTips":["Release plugins and server together so ABI versions stay in lockstep","Embed and log the SDK/ABI version in plugin metadata for quick diagnosis","Run a plugin smoke-test load in CI against the shipping server build"],"tags":["plugin","windows","abi","version-mismatch","dynamic-library"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}