{"record":{"id":"c2ebebd8a811985a","repo":"paperclipai/paperclip","slug":"process-tree-has-not-exited","errorCode":null,"errorMessage":"Process tree has not exited.","messagePattern":"Process tree has not exited\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/createos/src/execute.ts","lineNumber":215,"sourceCode":"      throw new CreateosCleanupError(\"CreateOS process creation could not be confirmed; destroy the lease before reusing it.\");\n    }\n    if (signal.aborted && signal.reason?.name === \"TimeoutError\") {\n      output.finish();\n      return {\n        exitCode: null, timedOut: true, stdout: output.stdout, stderr: output.stderr,\n        metadata: { processId, outputTruncated: output.truncated },\n      };\n    }\n    if (signal.aborted) throw new Error(\"CreateOS command was cancelled.\");\n    throw error;\n  } finally {\n    const cleanupSignal = AbortSignal.timeout(client.config.timeoutMs);\n    // Do not hide a cleanup failure: the host must know containment is unproven.\n    try {\n      if (processId && !completed) {\n        try {\n          const termination = await client.json(`${base}/${processId}?grace_ms=1000`, \"DELETE\", undefined, cleanupSignal);\n          if (termination.tree_exited !== true) throw new Error(\"Process tree has not exited.\");\n        }\n        catch (error) { if (!(error instanceof CreateosApiError && error.status === 404)) throw new CreateosCleanupError(\"CreateOS command cleanup failed; process termination is unconfirmed.\"); }\n      }\n    } finally {\n      if (staged && stdinPath) {\n        // /files has no delete verb. /exec supplies a bounded, one-shot removal\n        // after the managed process finishes, without retaining another record.\n        await client.json(`/sandboxes/${id}/exec`, \"POST\", {\n          cmd: \"/bin/rm\", args: [\"-f\", \"--\", stdinPath],\n        }, cleanupSignal).catch(() => undefined);\n      }\n    }\n  }\n}\n","sourceCodeStart":197,"sourceCodeEnd":230,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/plugins/sandbox-providers/createos/src/execute.ts#L197-L230","documentation":"After a non-completed process, the finally block issues DELETE with grace_ms=1000 to terminate the process tree. If the termination response reports tree_exited !== true, containment is not proven, so execute() throws this error (which the inner catch converts into CreateosCleanupError). It prevents silently leaving a live process in the sandbox.","triggerScenarios":"The DELETE /processes/:id?grace_ms=1000 response returns tree_exited false — the process tree ignored SIGTERM/SIGKILL within the grace period, or the server reports exit asynchronously and the response races termination.","commonSituations":"Runaway or stuck child processes ignoring termination signals; very short grace_ms (1000ms) insufficient for a large process tree to die; server reporting state before reaping children.","solutions":["Destroy the whole sandbox lease to guarantee containment rather than trusting process-level termination.","Increase the grace_ms parameter if the API allows a longer termination window.","Poll process status after DELETE to confirm exit before treating the run as complete.","Investigate the command for processes that spawn detached children or trap signals."],"exampleFix":"// before\nif (termination.tree_exited !== true) throw new Error(\"Process tree has not exited.\");\n// after\nif (termination.tree_exited !== true) {\n  await client.json(`${base}/${processId}?grace_ms=5000`, \"DELETE\", undefined, cleanupSignal);\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const r = await execute(lease, cmd, { signal });\n  if (r instanceof CleanupUnconfirmed) await destroyLease(lease);\n  return r;\n} catch (e) {\n  await destroyLease(lease); // containment unproven: reclaim sandbox\n  throw e;\n}","preventionTips":["Destroy the lease whenever process termination is unconfirmed.","Avoid commands that leave detached/trap-happy child processes.","Allow a longer grace period for termination of large process trees."],"tags":["sandbox","process-termination","cleanup","containment"],"backgroundTag":"internal-invariant-violation","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}