{"record":{"id":"df3a030e966829c6","repo":"agalwood/Motrix","slug":"engineprocessterminationfailed","errorCode":"EngineProcessTerminationFailed","errorMessage":"aria2 process ${expectedPid} did not exit after force termination","messagePattern":"aria2 process (.+?) did not exit after force termination","errorType":"error_code","errorClass":"AppError","httpStatus":null,"severity":"critical","filePath":"src/core/engine/aria2/aria2-process-manager.ts","lineNumber":272,"sourceCode":"        'The process changed or is not verified as Motrix-owned'\n      )\n    }\n\n    if (\n      processInfo.ownership === EngineProcessOwnership.CurrentApp &&\n      this.getPid() === expectedPid\n    ) {\n      this.kill()\n    } else {\n      this.inspector.forceTerminate(expectedPid)\n    }\n\n    const deadline = Date.now() + 5_000\n    while (this.inspector.isAlive(expectedPid) && Date.now() < deadline) {\n      await new Promise<void>((resolve) => setTimeout(resolve, 100))\n    }\n    if (this.inspector.isAlive(expectedPid)) {\n      throw new AppError(\n        ErrorCode.EngineProcessTerminationFailed,\n        `aria2 process ${expectedPid} did not exit after force termination`\n      )\n    }\n    await this.clearOwnershipRecord(expectedPid)\n  }\n\n  private toProcessInfo(\n    inspected: InspectedProcess,\n    ownership: EngineProcessOwnership,\n    safeToTerminate: boolean\n  ): EngineProcessInfo {\n    return {\n      pid: inspected.pid,\n      name: inspected.name,\n      executableName: inspected.executablePath\n        ? path.basename(inspected.executablePath)\n        : null,","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/agalwood/Motrix/blob/1a708ee57746c434e2c67a44bbf0906a976afea4/src/core/engine/aria2/aria2-process-manager.ts#L254-L290","documentation":"Thrown as an AppError (code EngineProcessTerminationFailed) by Aria2ProcessManager.forceTerminateVerified after it sends a force-kill (SIGKILL via kill() or inspector.forceTerminate) and then polls inspector.isAlive(expectedPid) in a loop for up to 5 seconds (100ms intervals). If the process is still alive after the 5s deadline, this error fires. This indicates the OS could not terminate the process — typically a permissions issue or an uninterruptible state.","triggerScenarios":"forceTerminateVerified kills the verified process, then enters a wait loop (deadline = now + 5000ms, polling every 100ms); after the deadline, inspector.isAlive(expectedPid) still returns true.","commonSituations":"The process is running as a different user/root and the current process lacks kill permission; the process is in an uninterruptible sleep state (D state, e.g. stuck on a disk I/O or NFS); zombie process that hasn't been reaped by its parent; containerized environment where kill signals are restricted; the PID was reused by a new process.","solutions":["Manually kill the process with elevated privileges: sudo kill -9 <expectedPid>","Check the process state (ps -o pid,stat,cmd -p <expectedPid>) — if it's in D state, address the underlying I/O issue or reboot","If the PID was reused, verify with inspectPort and update the expected PID","Restart the application or the host to clear the stuck process","In containers, ensure the init process (tini/dumb-init) forwards signals correctly"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await processManager.forceTerminateVerified(expectedPid, port, expected)\n} catch (e) {\n  if (e instanceof AppError && e.code === ErrorCode.EngineProcessTerminationFailed) {\n    // Process won't die — escalate to OS-level kill or prompt user to restart\n    log.error({ pid: expectedPid }, 'force termination failed, manual intervention required')\n    await promptUserRestart()\n  } else throw e\n}","preventionTips":["Check process state (ps -o pid,stat) before relying on force termination — D-state processes need a reboot","Ensure the app has sufficient OS permissions to kill the aria2 process","Use container init processes (tini/dumb-init) that properly forward signals in Docker/Podman"],"tags":["aria2","engine","process","termination","timeout","permissions"],"backgroundTag":null,"analyzedSha":"1a708ee57746c434e2c67a44bbf0906a976afea4","analyzedAt":"2026-08-12T16:18:09.346Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}