Okteto Environment Debugger
This skill triages broken Okteto environments. When a service is misbehaving, run through the triage algorithm below, apply the matching playbook, and emit a structured diagnosis. Do not guess — always let the command output drive the conclusion.
Diagnostics are
read-only:
,
,
, and
are fine here. Never mutate the cluster with raw
/
— fixes go through
and
(see the
skill for lifecycle operations, worktree isolation, and teardown rules).
Triage algorithm
Run these steps in order. Stop at the first step that identifies the failure.
Step 1: Verify connectivity and pin the namespace
If this fails, the user is disconnected from the cluster. Stop and help them reconnect (
) before proceeding.
The JSON output includes the active
. Capture it — every command below targets it explicitly as
:
bash
ns=$(okteto context show | jq -r .namespace)
If you are working in an isolated worktree namespace (see the
skill), use that namespace instead — the environment you need to debug lives there, not in the context's default.
kubectl must target the same cluster and namespace as Okteto. kubectl reads its own kubeconfig, which can point at a different namespace — or a different cluster entirely — than the Okteto context, especially when multiple agents or worktrees are active on the same machine. Run
to download credentials for the cluster selected via
, and pass
on every kubectl command. If
kubectl get pods -n "$ns"
errors or shows pods that don't match the services in
, fix the kubeconfig before trusting any diagnostic output.
Step 2: Discover services
Parse the
and
sections for canonical service names. Never hardcode service names — always derive them from
.
Step 3: Snapshot pod states
bash
kubectl get pods -n "$ns"
This is the master triage signal. Map each pod to one of these states and apply the matching playbook below:
If the user named a specific service, filter to that service's pods only. If no service was named, check all pods.
Playbooks
Crash loop (CrashLoopBackOff)
The container starts, crashes, and Kubernetes keeps restarting it.
bash
# Get logs from the previous (crashed) container instance
kubectl logs <pod-name> --previous -n "$ns"
# If that fails (first crash, no previous), get current logs
kubectl logs <pod-name> -n "$ns"
# Check exit code and liveness/readiness probe config
kubectl describe pod <pod-name> -n "$ns"
Look for:
- Exit code in — is an app error; is OOM (see OOM playbook); means the entrypoint command wasn't found
- The last lines of logs — the final error before crash is usually the root cause
- Liveness probe failures in events section — misconfigured health check paths or timeouts
Common root causes:
- Missing or wrong environment variable (
fatal: required env var FOO not set
)
- Can't connect to a dependency (database, message queue) that isn't ready yet
- Port mismatch between app and probe configuration
- Command/entrypoint not found (wrong base image or typo in okteto.yaml )
OOM kill (OOMKilled)
The container exceeded its memory limit and was killed by Kubernetes.
bash
kubectl describe pod <pod-name> -n "$ns"
Look for:
- in the section
- value under →
- Compare limit to how much memory the service actually needs
Fix pattern:
Increase the memory limit in the service's Helm values or
. Show the user the exact current limit and suggest a reasonable increase (typically 2×). Do not suggest removing limits entirely.
Image pull failure
Kubernetes can't pull the container image.
bash
kubectl describe pod <pod-name> -n "$ns"
Look for:
- in the Events section
- The exact image reference Kubernetes tried to pull (registry, repo, tag)
- vs — both mean the same thing, different retry states
Common root causes:
- Image doesn't exist (typo in tag, or was never run for this service)
- Image exists but is in a private registry with no pull credentials
- Tag was deleted or overwritten after a bad push
Fix pattern:
If the image should have been built by Okteto, run
. If the image is external, verify the tag exists. If credentials are the issue, help the user create an image pull secret.
Pending / unschedulable
The pod has been accepted by Kubernetes but hasn't been scheduled onto a node.
bash
kubectl describe pod <pod-name> -n "$ns"
# Also check recent namespace events for quota / resource pressure
kubectl get events -n "$ns" --sort-by=.lastTimestamp | tail -20
- or — node has no room; check resource requests
- — no node matches the scheduling constraints
node(s) had untolerated taint
— pod needs a toleration for a taint on the nodes
node(s) didn't match node affinity/selector
— nodeSelector or affinity rules are too strict
- Resource quota exceeded — check
kubectl describe resourcequota -n "$ns"
Fix pattern:
Match the error to the constraint. For resource requests, lower the request or ask the user to scale the node pool. For taints/selectors, show the current constraint and suggest removing or correcting it.
Runtime error (Running but unhealthy)
Pods are
but the service isn't responding, health checks are failing, or the user sees errors in requests.
bash
# Get recent application logs
okteto logs <service> --since 10m -n "$ns"
# If that's not enough context
okteto logs <service> --tail 200 -n "$ns"
Look for:
- Stack traces or lines — note the source file and line number
- Connection refused / timeout errors to dependencies — service is up but a downstream is not
- HTTP 5xx errors logged by a middleware or proxy
- "address already in use" — port conflict inside the container
Fix pattern:
Quote the most relevant 5–10 lines of the stack trace or error. Identify the source file if named. Suggest the specific fix — a code change, a missing env var, or a dependent service that needs to be started.
Deploy failure
The pods never appeared —
failed before creating them.
bash
# Check if the manifest is valid first
okteto validate
# Check deploy logs if validate passes
okteto logs --deploy -n "$ns"
Look for:
- errors — YAML syntax, schema violations, missing required fields
- Helm template rendering errors in deploy logs
- Image build failures (Dockerfile errors, build context too large)
Fix pattern:
If
catches it, show the exact error and line. If it's a Helm error, show the template path. If it's a build error, show the Dockerfile stage that failed.
Sync / dev mode issue
All pods are
and
, but the developer's code changes aren't being reflected in the dev container.
reports the file-synchronization state of the active dev container. It only works while an
session is running — if there isn't one, there is nothing syncing; tell the user to start it.
bash
okteto status -n "$ns"
# If the summary isn't enough, get syncthing troubleshooting links
okteto status --info -n "$ns"
Look for:
- or
- File counts that aren't progressing
- A path in the sync output that doesn't match the actual source directory
The richest signal is the
terminal itself — sync errors and conflict warnings surface there first, and you cannot see that session. Ask the user to paste its output.
Fix pattern:
Check the
paths in
against the actual directory structure. If paths are correct, try
followed by
(the user must run
interactively — never run it yourself). If sync is stuck,
will generate a diagnostic bundle.
Output format
Always emit one block per unhealthy service:
## Diagnosis: <service-name>
**Root cause:** <one sentence>
**Evidence:**
<relevant excerpt from logs or describe output — 5 to 20 lines, no more>
**Fix:**
<exact command to run or code change to make>
**Confidence:** High / Medium / Low
Use Low confidence when:
- The container has only crashed once (no logs available)
- The error message is ambiguous or missing
- Multiple possible root causes match the evidence
If all pods are healthy, report:
All services are Running and Ready. No obvious failures detected.
If you're still seeing issues, run `okteto doctor` to generate a full diagnostic bundle.
Common gotchas
- kubectl and okteto can disagree — kubectl uses its own kubeconfig context, which may point at a different namespace or cluster than the Okteto context. If kubectl output doesn't match what commands report, run and re-check with before drawing any conclusion.
- fails on first crash — the container must have restarted at least once. Fall back to (current instance) or describe events.
- Exit code 137 = OOM, not app error — if you see in a CrashLoopBackOff, treat it as OOM kill, not a crash loop.
- pods don't have logs — skip entirely and go straight to + .
- vs — prefer for application output; use when you need or when the pod name is needed for .
- Never run as part of debugging — diagnose first. Only suggest teardown if the environment is unrecoverable and the user explicitly asks.
- Never run — it is interactive. If the fix requires re-entering dev mode, tell the user to run in their terminal.