{"record":{"id":"6b0f378e987bf3c4","repo":"ramensoftware/windhawk","slug":"mod-id-specified-in-the-source-code-doesn-t-match","errorCode":null,"errorMessage":"Mod id specified in the source code doesn't match","messagePattern":"Mod id specified in the source code doesn't match","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/windhawk-vscode/src/extension.ts","lineNumber":834,"sourceCode":"\t\t},\n\t\tinstallMod: async message => {\n\t\t\tconst data: InstallModData = message.data;\n\n\t\t\tlet installedModDetails: InstallModReplyData['installedModDetails'] = null;\n\t\t\tlet readBackError: WireError | undefined;\n\n\t\t\ttry {\n\t\t\t\twindhawkCompilerOutput?.clear();\n\t\t\t\twindhawkCompilerOutput?.hide();\n\n\t\t\t\tconst modId = data.modId;\n\t\t\t\tconst modSource = data.modSource;\n\n\t\t\t\tconst metadata = await extractMetadataOrThrow(this._utils.core, modSource, this._language);\n\t\t\t\tif (!metadata.id) {\n\t\t\t\t\tthrow new Error('Mod id must be specified in the source code');\n\t\t\t\t} else if (metadata.id !== modId) {\n\t\t\t\t\tthrow new Error('Mod id specified in the source code doesn\\'t match');\n\t\t\t\t}\n\n\t\t\t\tconst op = this._utils.core.installMod({\n\t\t\t\t\tstorageId: modId,\n\t\t\t\t\tsource: modSource,\n\t\t\t\t\tmetadata,\n\t\t\t\t\tdisabled: data.disabled,\n\t\t\t\t\tloggingEnabled: data.loggingEnabled,\n\t\t\t\t\tcompileLocally: this._alwaysCompileModsLocally,\n\t\t\t\t\ttrackInProfile: true,\n\t\t\t\t});\n\n\t\t\t\t// Track the operation for the duration of the install so\n\t\t\t\t// cancelInstallMod can find it, and drop it however it settles -\n\t\t\t\t// a completion, a failure, or the cancel itself.\n\t\t\t\tthis._currentInstallOps.set(modId, op);\n\t\t\t\tlet result: InstallModResult;\n\t\t\t\ttry {","sourceCodeStart":816,"sourceCodeEnd":852,"githubUrl":"https://github.com/ramensoftware/windhawk/blob/61d99ed8e182e1af1b60109612b6763ad1b4b74e/src/windhawk-vscode/src/extension.ts#L816-L852","documentation":"During install, extractMetadataOrThrow derives the id from the mod source and it is compared against the modId supplied by the panel message. If the source's id differs from the target storageId, the extension refuses to install to avoid writing a mod under the wrong identity.","triggerScenarios":"WindhawkPanel install flow where metadata.id !== data.modId — e.g. editing an existing mod's source to a new id but installing into the old slot, or mismatched casing.","commonSituations":"Duplicating a mod and changing its id but reusing a stale UI session; uploading a different mod's file under another mod's entry.","solutions":["Make the id inside the mod source's metadata match the modId passed to the install call","Update the caller so modId is derived from the source metadata instead of hardcoded","If renaming intentionally, create a fresh install with the new id"],"exampleFix":"// before\nid=old.mod.id  // installed as storageId 'new.mod.id'\n// after\nid=new.mod.id  // matches storageId","handlingStrategy":"validation","validationCode":"const meta = parseModMetadata(modSource);\nif (meta?.id && meta.id !== data.modId) {\n  console.warn(`id mismatch: source=${meta.id} target=${data.modId}`);\n}","typeGuard":"const idsMatch = (sourceId: string, storageId: string): boolean => sourceId === storageId;","tryCatchPattern":"try { await panel.installMod(data); } catch (e) { if (e.message.includes(\"doesn't match\")) promptIdCorrection(e); else throw e; }","preventionTips":["Derive the install target id from the source metadata instead of duplicating it","Refresh UI state after renaming a mod's id","Copy mod files wholesale, not partially, to avoid id drift"],"tags":["metadata","mod-install","identifier-mismatch"],"backgroundTag":"identifier-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"}