{"record":{"id":"568ef80c3fdfcfdb","repo":"ramensoftware/windhawk","slug":"install-failed","errorCode":"INSTALL_FAILED","errorMessage":"The mod could not be installed.","messagePattern":"The mod could not be installed\\.","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/windhawk-frontend/apps/windhawk-frontend/src/app/mocking/mockScenarios.ts","lineNumber":263,"sourceCode":"    },\n  },\n\n  'command-failure': {\n    description: 'Every mod command the host is asked to run fails.',\n    replies: {\n      enableMod: failsWith('ENABLE_FAILED', 'The mod could not be enabled.'),\n      deleteMod: failsWith('DELETE_FAILED', 'The mod could not be removed.'),\n      setModSettings: failsWith(\n        'SETTINGS_FAILED',\n        'The settings could not be saved.'\n      ),\n      updateModRating: failsWith('RATING_FAILED', 'The rating was not recorded.'),\n      // Install reports its outcome as the details it produced, so a failure is an\n      // absent mod rather than succeeded:false.\n      installMod: (reply) => ({\n        modId: reply['modId'],\n        installedModDetails: null,\n        error: { code: 'INSTALL_FAILED', message: 'The mod could not be installed.' },\n      }),\n    },\n  },\n\n  'dev-tools-missing': {\n    description:\n      'The development tools are not on the machine, so a launch offers to install them instead of opening an editor.',\n    replies: {\n      // What a host answers a launch with when the editor it would open is not\n      // there: no error object, because nothing failed - the app raises the\n      // install offer off this flag alone.\n      createNewMod: () => ({ uiMissing: true }),\n      editMod: () => ({ uiMissing: true }),\n      forkMod: () => ({ uiMissing: true }),\n    },\n  },\n\n  'update-source-failure': {","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/ramensoftware/windhawk/blob/61d99ed8e182e1af1b60109612b6763ad1b4b74e/src/windhawk-frontend/apps/windhawk-frontend/src/app/mocking/mockScenarios.ts#L245-L281","documentation":"A mock/dev-scenario install failure. installMod in this mock scenario returns installedModDetails: null with an error object { code: 'INSTALL_FAILED' } because install reports its outcome via the details it produced — a null details payload means the mod was not installed.","triggerScenarios":"The frontend is running against the mock API layer with the failing-install scenario enabled and calls installMod; the mock deliberately returns installedModDetails: null plus error code INSTALL_FAILED.","commonSituations":"Developers testing the panel UI's install-failure path; automated tests or storybook setups using mockScenarios to exercise error rendering.","solutions":["Verify you are connected to the real backend rather than the mock scenarios if you expect installs to succeed.","If you want install to succeed in dev, switch the mock scenario or make the mock return non-null installedModDetails.","Handle the returned error object in UI code so the failure is displayed instead of crashing on null details."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"if ('error' in reply && reply.error?.code === 'INSTALL_FAILED') {\n  showInstallFailure(reply.error.message);\n}","typeGuard":"const isInstallSuccess = (r: InstallReply): r is InstallReply & { installedModDetails: object } =>\n  r.error == null && r.installedModDetails != null;","tryCatchPattern":"try {\n  const details = await installMod(modId);\n} catch (e) {\n  if (e.code === 'INSTALL_FAILED') {\n    notify(`Install failed: ${e.message}`);\n    return;\n  }\n  throw e;\n}","preventionTips":["Remember installMod reports failure via null details + error object — always null-check installedModDetails.","Use a dedicated mock scenario for success paths when developing features unrelated to install failures.","Render the error message from the reply instead of assuming details exist."],"tags":["mock","install","testing"],"backgroundTag":"api-error-response","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"}