janhq/jan · critical · Error

Router failed its health check on backend ${targetBackendStr

Error message

Router failed its health check on backend ${targetBackendString}

What it means

Post-update health-check failure: after downloading and switching to the new backend, restartRouterAndProbe() is called to restart the llama.cpp router and probe it. If the probe fails (router did not come up healthy), the update is considered failed and the error propagates. The catch block then attempts a rollback via rollbackBackendSelection.

Source

Thrown at extensions/llamacpp-extension/src/index.ts:1925

      if (IS_WINDOWS) {
        await new Promise((resolve) => setTimeout(resolve, 1000))
      }

      await this.commitBackendSelection(version, backend)

      if (await this.restartRouterAndProbe()) {
        logger.info(`Successfully updated to backend: ${targetBackendString}`)
        await this.pruneOldBackendVersions(version, backend)
        await this.recordUpdateHistory({
          from,
          to: targetBackendString,
          outcome: 'updated',
          durationMs: Date.now() - startedAt,
        })
        return { wasUpdated: true, newBackend: targetBackendString }
      }

      throw new Error(
        `Router failed its health check on backend ${targetBackendString}`
      )
    } catch (error) {
      logger.error('Backend update failed:', error)
      const rollbackOutcome = await this.rollbackBackendSelection(previous)
      await this.recordUpdateHistory({
        from,
        to: targetBackendString,
        outcome:
          rollbackOutcome === 'not-attempted' ? 'failed' : rollbackOutcome,
        error: String(error),
        durationMs: Date.now() - startedAt,
      })
      return { wasUpdated: false, newBackend: this.config.version_backend }
    } finally {
      this.isUpdatingBackend = false
      this.currentUpdate = null
    }

View on GitHub (pinned to fad3f12a14)

Solutions

  1. Check the router logs for the crash reason — missing .so/.dll or GPU errors are the most common.
  2. If switching to a CUDA backend, ensure the CUDA runtime DLLs are installed (installCudaRuntime) and the GPU driver is compatible.
  3. Verify no other process is using the router's listen port.
  4. Allow the automatic rollback to restore the previous working backend; if rollback also fails, manually select a known-good backend.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await extension.runUpdate(targetBackendString)
} catch (e) {
  if (e instanceof Error && e.message.includes('health check')) {
    // rollback is automatic; inform the user and suggest checking GPU/CUDA setup
    console.error('Update failed; previous backend restored. Check GPU drivers and CUDA runtime.')
  } else {
    throw e
  }
}

Prevention

When it happens

Trigger: The new backend binary launched but crashed or hung: missing shared libraries (e.g. CUDA runtime DLLs not installed), incompatible GPU driver, port conflict on the router's listen port, the binary segfaulted on startup, or the health probe timed out.

Common situations: Switching from CPU to CUDA backend without the matching CUDA toolkit/driver installed; switching to a backend version with a known startup regression; another process occupying the router port; GPU out of memory at launch.

Related errors


AI-assisted analysis of janhq/jan@fad3f12a14 (2026-08-12). Data as JSON: /api/errors/a3d4842656b01011. Report an issue: GitHub.