{"record":{"id":"4357d0a5f67f1399","repo":"alibaba/arthas","slug":"cannot-terminate-terminated-process","errorCode":null,"errorMessage":"Cannot terminate terminated process","messagePattern":"Cannot terminate terminated process","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"warning","filePath":"core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java","lineNumber":244,"sourceCode":"    public void toForeground(Handler<Void> completionHandler) {\n        if (processStatus == ExecStatus.RUNNING) {\n            if (!processForeground) {\n                updateStatus(ExecStatus.RUNNING, null, true, foregroundHandler, terminatedHandler, completionHandler);\n            }\n        } else {\n            throw new IllegalStateException(\"Cannot set to foreground a process in \" + processStatus + \" state\");\n        }\n    }\n\n    @Override\n    public void terminate() {\n        terminate(null);\n    }\n\n    @Override\n    public void terminate(Handler<Void> completionHandler) {\n        if (!terminate(-10, completionHandler, null)) {\n            throw new IllegalStateException(\"Cannot terminate terminated process\");\n        }\n    }\n\n    private synchronized boolean terminate(int exitCode, Handler<Void> completionHandler, String message) {\n        if (processStatus != ExecStatus.TERMINATED) {\n            //add status message\n            this.appendResult(new StatusModel(exitCode, message));\n            if (process != null) {\n                processOutput.close();\n            }\n            updateStatus(ExecStatus.TERMINATED, exitCode, false, endHandler, terminatedHandler, completionHandler);\n            if (process != null) {\n                process.unregister();\n            }\n            return true;\n        } else {\n            return false;\n        }","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/alibaba/arthas/blob/21cf2e9ba52b305290be7223b980ff504bb9cb5b/core/src/main/java/com/taobao/arthas/core/shell/system/impl/ProcessImpl.java#L226-L262","documentation":"Thrown by Process.terminate() when the internal terminate() method returns false, which happens only when the process is already in the TERMINATED state (the guard checks processStatus != TERMINATED). Terminating an already-dead process is a no-op that Arthas flags as an error.","triggerScenarios":"Calling terminate() (or 'kill <jobId>') on a job whose process has already finished and transitioned to TERMINATED.","commonSituations":"Double-kill in automation. User presses Ctrl+C or runs kill on a job that already completed naturally.","solutions":["Check job status before terminating — ignore TERMINATED jobs.","Wrap kill in a try-catch for IllegalStateException and treat it as already-done."],"exampleFix":"// before\njob.process().terminate();\n\n// after\nif (job.process().status() != ExecStatus.TERMINATED) {\n    job.process().terminate();\n}","handlingStrategy":"type-guard","validationCode":"if (process.status() != ExecStatus.TERMINATED) {\n    process.terminate();\n}","typeGuard":"boolean canTerminate(Process p) {\n    return p.status() != ExecStatus.TERMINATED;\n}","tryCatchPattern":"try {\n    process.terminate();\n} catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Cannot terminate terminated\")) {\n        // already dead; safe to ignore\n    }\n}","preventionTips":["Check process status before terminating.","Treat double-terminate as benign in automation by catching IllegalStateException."],"tags":["process-state","terminate","lifecycle"],"backgroundTag":null,"analyzedSha":"21cf2e9ba52b305290be7223b980ff504bb9cb5b","analyzedAt":"2026-08-14T00:57:07.243Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}