Skip to content

k8s: detect OOM/preemption as structured failure reasons (REMOTE-2111)#100

Draft
seemeroland wants to merge 1 commit into
mainfrom
oz-agent/REMOTE-2111/k8s-oom-preemption-observability
Draft

k8s: detect OOM/preemption as structured failure reasons (REMOTE-2111)#100
seemeroland wants to merge 1 commit into
mainfrom
oz-agent/REMOTE-2111/k8s-oom-preemption-observability

Conversation

@seemeroland

Copy link
Copy Markdown
Contributor

Context

Addresses REMOTE-2111: enterprise customer (IMC) asked how k8s worker pods handle OOM kills and pod preemptions.

Current behavior: when a k8s worker pod is OOM-killed or preempted, the cloud agent run fails with no state preservation, no snapshotting, and no resumption. This PR does not change that (checkpointing is a larger investment), but improves observability so users and operators know why a run failed.

Changes

Preemption detection

  • inspectPodFailure now checks for pod preemption via two signals:
    1. Kubernetes event with Reason == "Preempting" (emitted by the scheduler before eviction)
    2. Pod.Status.Phase == Failed with Status.Reason == "Evicted" and a message containing "preempt" (covers different k8s versions and eviction plugins)
  • Classified as new pod_preempted failure reason (previously fell through as generic job_failed or container_exit)

OOM classification already existed but is now surfaced better

  • classifyTerminatedReason("OOMKilled")container_oom was already tracked in metrics; now also carried through in user-facing messages and the wire protocol

Structured FailureReason in TaskFailedMessage

  • New optional FailureReason string field (JSON: failure_reason) so the server can identify OOM/preemption without parsing the human-readable message string
  • Companion warp-server PR accepts this field and logs it

Better user-facing error messages

  • container_oom: "The task container was terminated because it ran out of memory (OOM killed). Consider increasing the runner memory limit or reducing the task's memory usage."
  • pod_preempted: "The task pod was preempted by the Kubernetes scheduler (evicted to make room for higher-priority workloads). The run was not checkpointed — please retry. Consider using higher-priority pods or nodes with sufficient capacity."

Testing

  • go test ./internal/worker/... passes
  • go build ./... passes

Conversation: https://staging.warp.dev/conversation/c5421a3c-e5ac-459e-bf33-9c988a87de8a
Run: https://oz.staging.warp.dev/runs/019f4843-caaf-719a-861a-dd6cd9042bba

This PR was generated with Oz.

- Add TaskFailureReasonPodPreempted metric constant + priming entry.
- inspectPodFailure: detect pod preemption via Kubernetes event reason
  "Preempting" and via pod Status.Reason=="Evicted" with a message
  containing "preempt" (covers different k8s versions / eviction plugins).
- TaskFailedMessage: add FailureReason field (json:"failure_reason") so
  the server can identify OOM/preemption without parsing the human-readable
  Message string.
- executeTask/sendTaskFailed: propagate the structured failure reason from
  backendFailureError into the wire message.
- userFacingTaskError: return distinct, actionable messages for container_oom
  and pod_preempted failure reasons instead of the raw error string.

Current behavior for context: when a k8s worker pod is OOM-killed or
preempted, the cloud agent run fails with no state preservation and no
resumption mechanism. These changes surface the specific failure cause in
metrics, the user-facing error message, and the server-visible FailureReason
field for better observability and timeline display.

Co-Authored-By: Oz <oz-agent@warp.dev>
@seemeroland seemeroland added the from-feedback-bot Linear issue delegated from Feedback Bot label Jul 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

from-feedback-bot Linear issue delegated from Feedback Bot

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant