ramensoftware/windhawk · warning

INSTALL_FAILED

INSTALL_FAILED

Error message

The mod could not be installed.

What it means

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.

Solutions

  1. Verify you are connected to the real backend rather than the mock scenarios if you expect installs to succeed.
  2. If you want install to succeed in dev, switch the mock scenario or make the mock return non-null installedModDetails.
  3. Handle the returned error object in UI code so the failure is displayed instead of crashing on null details.
Defensive patterns

Strategy: fallback

Validate before calling

if ('error' in reply && reply.error?.code === 'INSTALL_FAILED') {
  showInstallFailure(reply.error.message);
}

Type guard

const isInstallSuccess = (r: InstallReply): r is InstallReply & { installedModDetails: object } =>
  r.error == null && r.installedModDetails != null;

Try / catch

try {
  const details = await installMod(modId);
} catch (e) {
  if (e.code === 'INSTALL_FAILED') {
    notify(`Install failed: ${e.message}`);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Developers testing the panel UI's install-failure path; automated tests or storybook setups using mockScenarios to exercise error rendering.


AI-assisted analysis of ramensoftware/windhawk@61d99ed8e1 (2026-09-12). Data as JSON: /api/errors/568ef80c3fdfcfdb. Report an issue: GitHub.

Appendix: source

Thrown at src/windhawk-frontend/apps/windhawk-frontend/src/app/mocking/mockScenarios.ts:263

    },
  },

  'command-failure': {
    description: 'Every mod command the host is asked to run fails.',
    replies: {
      enableMod: failsWith('ENABLE_FAILED', 'The mod could not be enabled.'),
      deleteMod: failsWith('DELETE_FAILED', 'The mod could not be removed.'),
      setModSettings: failsWith(
        'SETTINGS_FAILED',
        'The settings could not be saved.'
      ),
      updateModRating: failsWith('RATING_FAILED', 'The rating was not recorded.'),
      // Install reports its outcome as the details it produced, so a failure is an
      // absent mod rather than succeeded:false.
      installMod: (reply) => ({
        modId: reply['modId'],
        installedModDetails: null,
        error: { code: 'INSTALL_FAILED', message: 'The mod could not be installed.' },
      }),
    },
  },

  'dev-tools-missing': {
    description:
      'The development tools are not on the machine, so a launch offers to install them instead of opening an editor.',
    replies: {
      // What a host answers a launch with when the editor it would open is not
      // there: no error object, because nothing failed - the app raises the
      // install offer off this flag alone.
      createNewMod: () => ({ uiMissing: true }),
      editMod: () => ({ uiMissing: true }),
      forkMod: () => ({ uiMissing: true }),
    },
  },

  'update-source-failure': {

View on GitHub (pinned to 61d99ed8e1)