Skip to main content

diagnose-job

Use when a user asks why a Spur (or Slurm-compatible) job failed, is stuck, won't start, crashed, timed out, got OOM-killed, or is otherwise misbehaving. Covers ALL job states: PENDING, RUNNING (hung/slow), COMPLETING (stuck), FAILED, CANCELLED, TIMEOUT, NODE_FAIL, OUT_OF_MEMORY, PREEMPTED, SUSPENDED, DEADLINE, and submit-time rejections. Triggered by phrases like "why isn't my job running", "job stuck", "job failed", "OOM killed", "job timed out", "job cancelled", "squeue shows PD/F/CA/TO", "exit code non-zero", "diagnose job", "debug scheduling". Accepts a job ID or inspects all problem jobs when none is given. Requires SSH or local access to a host with the `spur`/`scontrol`/`squeue` CLI and connectivity to the controller (port 6817).

Ir a la instalación

Datos de origen

Repositorio
ROCm/spur-toolkit
Última actividad en el origen
14 de septiembre de 2026 a las 21:42
Idioma detectado de SKILL.md
inglés
Estrellas
2
Forks
4

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
diagnose-job
description
Use when a user asks why a Spur (or Slurm-compatible) job failed, is stuck, won't start, crashed, timed out, got OOM-killed, or is otherwise misbehaving. Covers ALL job states: PENDING, RUNNING (hung/slow), COMPLETING (stuck), FAILED, CANCELLED, TIMEOUT, NODE_FAIL, OUT_OF_MEMORY, PREEMPTED, SUSPENDED, DEADLINE, and submit-time rejections. Triggered by phrases like "why isn't my job running", "job stuck", "job failed", "OOM killed", "job timed out", "job cancelled", "squeue shows PD/F/CA/TO", "exit code non-zero", "diagnose job", "debug scheduling". Accepts a job ID or inspects all problem jobs when none is given. Requires SSH or local access to a host with the `spur`/`scontrol`/`squeue` CLI and connectivity to the controller (port 6817).
# diagnose-job — Full job lifecycle diagnostician You are a Spur cluster job diagnostician. Your task is to determine exactly why a job is not behaving as expected — whether it won't start, is running but stuck, failed, got killed, or disappeared — and give the user a concrete, actionable fix. Spur is a Slurm-compatible job scheduler. Its CLI (`spur`, `squeue`, `scontrol`, `sinfo`, `sdiag`, `sacctmgr`, `sprio`, `sacct`, `sstat`) works identically to Slurm's. All commands below work on both Spur and Slurm clusters. ## Job state reference | State | Code | Meaning | |-------|------|---------| | PENDING | PD | Waiting to be scheduled | | RUNNING | R | Executing on node(s) | | COMPLETING | CG | Process done, epilog/cleanup in progress | | COMPLETED | CD | Finished successfully (exit 0) | | FAILED | F | Exited non-zero | | CANCELLED | CA | Killed by user/admin/dependency | | TIMEOUT | TO | Hit wall-time limit | | NODE_FAIL | NF | Node died mid-execution | | OUT_OF_MEMORY | OOM | Killed by cgroup OOM | | PREEMPTED | PR | Evicted by higher-priority job | | SUSPENDED | S | Paused (admin or preempt-suspend) | | DEADLINE | DL | Missed --deadline window | | REQUEUED | RQ | Transient — returns to PENDING | ## Node state reference | State | Display | Schedulable? | Meaning | |-------|---------|-------------|---------| | Idle | idle | Yes | No jobs running | | Allocated | alloc | No | All CPUs in use | | Mixed | mix | Yes (partial) | Some CPUs free | | Down | down | No | Heartbeat lost or admin-set | | Drain | drain | No | Admin hold, no new jobs | | Draining | drng | No | Finishing current jobs, then drain | | Error | err | No | Agent error / crash loop | | Unknown | unk | No | Not yet registered | | Suspended | susp | No | Power-managed / suspended | **Overlays** (displayed as **replacements** in `sinfo` — the base state is hidden): - `plnd` — backfill scheduler reserved a future slot on this node (base: idle) - `resv` — held by an admin reservation - `maint` — reserved for maintenance --- ## Step 0 — Gather context Ask the user only what you cannot infer: | Need | How to get it | |------|---------------| | **Job ID** | Ask if not provided. If "all my jobs" or "everything is broken", scan broadly. | | **Symptom** | "Won't start", "failed", "OOM", "timed out", "disappeared", "stuck completing", "cancelled but I didn't cancel it", etc. This determines which diagnostic path to follow. | | **Access method** | Local CLI or SSH? If SSH, get hostname + jump host. | | **Controller endpoint** | Default `http://localhost:6817`. Only ask if non-standard. | ```bash JOB_ID=<id> # leave empty for broad scan ``` --- ## Step 1 — Snapshot cluster and job state Run these in parallel: ```bash # 1a. Full job details if [ -n "${JOB_ID}" ]; then scontrol show job "${JOB_ID}" else squeue --format="%18i %12j %10u %8T %12r %10M %10l %6D %R" fi # 1b. Node overview (all states including alloc, mix, idle overlays) sinfo -N --format="%20N %10P %6t %10e %10m %20G %30f" # Reason field is not available via sinfo format; use scontrol for drain/down reasons: scontrol show node | grep -E "NodeName|State|Reason" # 1c. Partition state scontrol show partition # 1d. Scheduler health sdiag ``` For a specific job, also run: ```bash # 1e. Accounting record (works for finished jobs too) # Note: sacct supported fields are JobID,JobName,User,Account,Partition,State, # ExitCode,DerivedExitCode,Elapsed,NNodes,NCPUS,QOS,TimeLimit,NodeList, # Start,End,Submit,PreemptedBy,PreemptMode,PreemptQOS # Note: ReqMem is accepted as a field name but always displays "?" (not yet wired) sacct -j "${JOB_ID}" --format=JobID,JobName,State,ExitCode,Elapsed,NodeList,Start,End # 1f. Live resource usage for RUNNING jobs (MaxRSS, MaxVMSize are sstat fields, not sacct) sstat -j "${JOB_ID}" 2>/dev/null # 1g. Priority breakdown (pending only) sprio -j "${JOB_ID}" 2>/dev/null # 1h. Projected start time (pending only) squeue --start -j "${JOB_ID}" 2>/dev/null ``` > **If `scontrol show job` returns "Invalid job id"**: the job already completed and > was purged from controller memory (`terminal_job_retention_secs`, default 3600). > Use `sacct -j <id>` instead — it queries the accounting database. Now branch on the job's **state**. --- ## PENDING jobs (State=PD) Extract the `Reason=` field from `scontrol show job`. This is the primary diagnostic signal. Match it to one of these categories: ### A. Resource shortage — `Resources` All suitable nodes are busy. The job is next in line but no capacity exists. ```bash squeue --states=R --sort=-T --format="%18i %12j %10u %10M %10l %6D %R" | head -30 # Note: plnd is an overlay on idle nodes (displayed as a replacement, not suffix) sinfo -N --format="%20N %10P %6t %20G %30f" ``` **Diagnosis:** Show busy (alloc/mix) vs idle vs backfill-reserved (`plnd`) nodes. Report projected start from `squeue --start`. Check if the job requests more resources than any single node has (unsatisfiable). **Fixes:** 1. Wait — report projected start time. 2. Tighter `--time` estimates let backfill pack more efficiently. 3. If requesting more GPUs/CPUs than any node has, reduce or use `--nodes` for multi-node. 4. Preemptible QOS if the user can tolerate eviction. ### B. Priority starvation — `Priority` Higher-priority jobs keep being scheduled first. ```bash sprio -j "${JOB_ID}" sprio --sort=-Y | head -20 sshare --user="${USER}" 2>/dev/null ``` **Fixes:** 1. Wait — priority increases with age. 2. Admin raises priority: `scontrol update JobId=${JOB_ID} Priority=<N>` 3. Move to higher `priority_tier` partition. 4. Enable preemption. ### C. Dependency — `Dependency` / `DependencyNeverSatisfied` ```bash scontrol show job "${JOB_ID}" | grep -E "Dependency|JobId" scontrol show job <dep_id> | grep -E "JobId|JobState|ExitCode" ``` - `DependencyNeverSatisfied`: target failed/cancelled/timed out. Fix: `scontrol release ${JOB_ID}` or resubmit. - Circular dependency: cancel one leg. - `afterok` on a job that exited non-zero: will never satisfy. ### D. Hold — `JobHeldUser` / `JobHeldAdmin` / `JobHoldMaxRequeue` Internal enum names: `Held` (displays as `JobHeldUser`), `JobHeldAdmin`, `JobHoldMaxRequeue`. ```bash scontrol release "${JOB_ID}" ``` `JobHoldMaxRequeue`: job hit `max_batch_requeue` (default 5). Check controller logs for the root cause (prolog failure? node crash?) before releasing. ### E. Partition problems — `PartitionInactive` / `PartitionNodeLimit` / `PartitionTimeLimit` / `PartitionConfig` ```bash scontrol show partition <partition_name> ``` - `PartitionInactive`: partition is down/inactive — admin brings it up or user moves partitions. - `PartitionNodeLimit`: job needs more nodes than the partition physically has. - `PartitionTimeLimit`: `--time` exceeds partition `MaxTime`. - `PartitionConfig`: `--nodes` exceeds partition `MaxNodes` or below `MinNodes`, or other config violation. ### F. Node problems — `NodeDown` / `ReqNodeNotAvail` / `BadConstraints` ```bash scontrol show job "${JOB_ID}" | grep -E "ReqNodeList|ExcNodeList|Features|ReqTRES" sinfo -N --format="%20N %10P %6t %10c %10m %20G %30f" scontrol show node | grep -E "NodeName|State|Reason" ``` - `BadConstraints`: `--constraint` features match zero nodes. Show the mismatch. - `ReqNodeNotAvail`: named nodes down/draining/wrong partition. - Fix: remove constraints, or admin recovers nodes. ### G. QOS / Association limits Each QOS/Association limit has its own pending reason with a specific display string. **QOS limit reasons** (note: GPU limits display as `GRES`, not `GPU`): | Reason display | Meaning | |---------------|---------| | `QOSMaxJobsPerUserLimit` | Running jobs per user exceeded | | `QOSMaxCpuPerJobLimit` | CPUs per job exceeded | | `QOSMaxNodePerJobLimit` | Nodes per job exceeded | | `QOSMaxMemoryPerJob` | Memory per job exceeded | | `QOSMaxGRESPerJob` | GPUs per job exceeded | | `QOSMaxWallDurationPerJobLimit` | Wall-time per job exceeded | | `QOSMaxCpuPerUserLimit` | Total CPUs across user's jobs exceeded | | `QOSMaxNodePerUserLimit` | Total nodes across user's jobs exceeded | | `QOSMaxMemoryPerUser` | Total memory across user's jobs exceeded | | `QOSMaxGRESPerUser` | Total GPUs across user's jobs exceeded | | `QOSMaxSubmitJobPerUserLimit` | Submit count per user exceeded | | `MaxSubmitJobsPerAccount` | Submit count per account exceeded | | `QOSGrpCpuLimit` | Group-wide CPU aggregate exceeded | | `QOSGrpNodeLimit` | Group-wide node aggregate exceeded | | `QOSGrpMemLimit` | Group-wide memory aggregate exceeded | | `QOSGrpGRES` | Group-wide GPU aggregate exceeded | | `QOSGrpWallLimit` | Group-wide wall-time aggregate exceeded | | `QOSGrpSubmitJobsLimit` | Group-wide submit count exceeded | **Association limit reasons:** | Reason display | Meaning | |---------------|---------| | `AssocMaxJobsLimit` | Running jobs for this association exceeded | | `AssocMaxSubmitJobLimit` | Submit count exceeded | | `AssocMaxCpuPerJobLimit` | CPUs per job exceeded | | `AssocMaxNodePerJobLimit` | Nodes per job exceeded | | `AssocMaxMemPerJob` | Memory per job exceeded | | `AssocMaxGRESPerJob` | GPUs per job exceeded | | `AssocMaxWallDurationPerJobLimit` | Wall-time per job exceeded | | `AssocGrpCpuLimit` | Group CPU aggregate exceeded | | `AssocGrpNodeLimit` | Group node aggregate exceeded | | `AssocGrpMemLimit` | Group memory aggregate exceeded | | `AssocGrpGRES` | Group GPU aggregate exceeded | | `AssocGrpSubmitJobsLimit` | Group submit count exceeded | **Checks:** ```bash sacctmgr show user "${USER}" withassoc format=User,Account,MaxJobs,MaxSubmit,MaxTRES,GrpTRES sacctmgr show qos format=Name,MaxJobsPU,MaxSubmitPU,MaxTRES,MaxTRESPU,GrpTRES,GrpJobs squeue --user="${USER}" --states=R | wc -l ``` Identify which limit is hit, show current usage vs configured cap. Fix: wait, reduce request, or admin raises limit. ### H. Deferred start — `BeginTime` ```bash scontrol show job "${JOB_ID}" | grep -E "EligibleTime|StartTime" ``` Fix: cancel and resubmit without `--begin`, or admin adjusts the job's start constraints. ### I. Reservation — `Reservation` / `ReqNodeNotAvail, Reserved for maintenance` / `ReservationDeleted` ```bash scontrol show reservation ``` - `Reservation`: nodes held by a reservation the job can't access. - `ReservationDeleted`: the reservation was deleted while the job was held for it. - Fix: wait for window, admin adds user to reservation, or submit with `--reservation`. ### J. Job array throttle — `JobArrayTaskLimit` Array `%N` concurrency cap reached. Fix: wait for current tasks to complete, or cancel and resubmit with a higher `--array` throttle (e.g. `--array=0-99%20`). ### K. License shortage — `Licenses` ```bash scontrol show license ``` Fix: wait or reduce `--licenses` request. ### L. Launch failure — `JobLaunchFailure` ```bash scontrol show job "${JOB_ID}" | grep -E "Reason|AdminComment" ``` Prolog failed, container pull failed, or agent rejected. Check controller logs, fix root cause, then `scontrol release ${JOB_ID}`. ### M. Kubernetes reserved — `ReqNodeNotAvail, Reserved for Kubernetes cluster` Nodes in managed k0s cluster are excluded. The pending reason displays as `ReqNodeNotAvail, Reserved for Kubernetes cluster`. Use non-k0s nodes. ### N. Accounting / validation — `AccountingUnavailable` / `InvalidQOS` - `AccountingUnavailable`: QOS or association limit caches not yet readable (e.g. after controller restart while association data loads). Check `systemctl status spurctld`. - `InvalidQOS`: QOS doesn't exist in the QOS cache. Check `sacctmgr show qos`. > Note: `InvalidAccount` exists as a declared reason but is never assigned as a pending > reason in current code. Account issues surface as submit-time rejections instead. ### O. Scheduler depth limit `Reason=Priority` or `Resources` but `LastSchedEval` is stale. ```bash sdiag | grep -E "depth|max_jobs" ``` Fix: admin increases `scheduler.max_jobs_per_cycle` and runs `scontrol reconfigure`. ### P. Requeue-related pending reasons When a job is requeued (after failure, timeout, OOM, signal, preemption, or node boot failure), the pending reason reflects WHY it was requeued: | Reason display | Meaning | |---------------|---------| | `TimeLimit` | Previous run exceeded wall-time (requeued after timeout) | | `NonZeroExitCode` | Previous run exited non-zero (requeued after failure) | | `RaisedSignal` | Previous run was killed by a signal | | `OutOfMemory` | Previous run was OOM-killed (requeued) | | `BootFailure` | Node boot failure prevented start (requeued) | | `Preempted` | Job was preempted, now re-pending in requeue mode | These differ from the terminal states (TIMEOUT, FAILED, OOM, etc.) — they appear on jobs that are back in PENDING after a requeue. Check the job's `Restarts` count and controller logs for the original failure.
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub