{"record":{"id":"0b0f9e4b14fdba44","repo":"ramensoftware/windhawk","slug":"windhawk-core-contract-version-mismatch-dll-has-info","errorCode":null,"errorMessage":"windhawk-core contract version mismatch: DLL has ${info.contractVersion}, client expects ${CONTRACT_VERSION}","messagePattern":"windhawk-core contract version mismatch: DLL has (.+?), client expects (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/windhawk-vscode/src/coreClient/dllBackend.ts","lineNumber":263,"sourceCode":"// in-process fallback). `bridgeOverride` injects a fake bridge for tests (the\n// production path loads the prebuilt .node from disk).\nexport function createDllBackend(options: DllBackendOptions, bridgeOverride?: BridgeModule): DllBackend {\n\tconst { appRoot, windhawkVersion, userAgent, logger } = options;\n\n\tconst bridge = bridgeOverride ?? loadBridgeFromDisk();\n\n\t// The bridge validates WhCoreGetAbiVersion itself; the contract version\n\t// is validated here, where the contract lives.\n\tconst library = bridge.loadCore(resolveDllPath(appRoot));\n\tconst info = JSON.parse(library.getInfoJson()) as { contractVersion: string };\n\tif (info.contractVersion !== CONTRACT_VERSION) {\n\t\t// Version skew must be loud: this is a packaging error, not a normal\n\t\t// missing-artifact development state.\n\t\tconst message =\n\t\t\t`windhawk-core contract version mismatch: DLL has ${info.contractVersion}, ` +\n\t\t\t`client expects ${CONTRACT_VERSION}`;\n\t\tlogger.error(message);\n\t\tthrow new Error(message);\n\t}\n\n\t// In-flight async operations, keyed by the operation id the bridge\n\t// reports. JS is single-threaded and the bridge queues onEvent onto the\n\t// event loop, so a handler registered synchronously after invokeAsync\n\t// returns is in place before any of its operation's events can dispatch.\n\tconst opHandlers = new Map<number, (event: OperationEvent) => void>();\n\n\tconst session = library.createSession(\n\t\tJSON.stringify({\n\t\t\tappRootPath: appRoot,\n\t\t\twindhawkVersion,\n\t\t\tuserAgent,\n\t\t\tdebugOverrides: {\n\t\t\t\tmodsUrlRoot: debugModsUrlRoot() ?? null,\n\t\t\t\tupdateUrl: debugUpdateInstallerUrl() ?? null,\n\t\t\t\tinstallerRegKey: debugInstallerRegKeyString() ?? null,\n\t\t\t\tschtasksPath: debugSchtasksPath() ?? null,","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/ramensoftware/windhawk/blob/61d99ed8e182e1af1b60109612b6763ad1b4b74e/src/windhawk-vscode/src/coreClient/dllBackend.ts#L245-L281","documentation":"createDllBackend() loads the native bridge and reads its reported contractVersion, comparing it to the client's CONTRACT_VERSION constant. On mismatch it logs and throws, because the ABI between JS client and windhawk-core DLL is incompatible — this is treated as a packaging error that must fail loudly rather than corrupt state.","triggerScenarios":"Extension updated (or the DLL swapped) so the shipped windhawk-core DLL version differs from the CONTRACT_VERSION compiled into the client; createWindhawkCore is then called.","commonSituations":"Partial upgrade where extension and core DLL came from different versions; manually replacing the DLL with a dev build; a package manager pinned an old core.","solutions":["Reinstall/update both the extension and the windhawk-core DLL from the same release so versions align","Verify the DLL's contractVersion matches CONTRACT_VERSION in dllBackend.ts (log info.contractVersion)","Downgrade the extension or upgrade the core binary to the matching version pair"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"const info = bridge.getInfo?.();\nif (info && info.contractVersion !== CONTRACT_VERSION) {\n  console.error(`version skew: dll=${info.contractVersion} client=${CONTRACT_VERSION}`);\n}","typeGuard":"const versionsMatch = (info: { contractVersion: number }): boolean => info.contractVersion === CONTRACT_VERSION;","tryCatchPattern":"try { const core = await createWindhawkCore(); } catch (e) { if (e.message.includes('contract version mismatch')) promptReinstallMatchingVersions(); else throw e; }","preventionTips":["Always ship extension and core DLL from the same release","Bump CONTRACT_VERSION and regenerate/repackage together on ABI changes","Log both versions at startup to catch skew early"],"tags":["versioning","native","compatibility"],"backgroundTag":"contract-version-mismatch","analyzedSha":"61d99ed8e182e1af1b60109612b6763ad1b4b74e","analyzedAt":"2026-09-12T14:02:41.115Z","contentChangedAt":"2026-09-12T14:02:41.115Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}