Home / OCI

OCICheat sheetIntermediate

OCI work requests cheat sheet: track async operations and find out why they failed

Many OCI operations return before the work is done. Use work requests to see what is still running, what failed and the error text, for Compute, OKE, Load Balancer and other services.

Deepak Bhardwaj6 min read

Applies toOCI CLI 3.x; generic Work Requests API (Compute and other Core operations), OKE (oci ce), Load Balancer (oci lb) and other services with their own work-request commands

When you need this

A launch, resize, volume attach, node pool update or load balancer change "succeeded" in the CLI or console, but the resource never changed. Or a script hangs waiting on an OCID whose state never moves. The API call only accepted the request. The actual work runs asynchronously and is tracked as a work request. A work request also carries the error message you never saw.

Use this sheet to:

  • find the work request behind a resource
  • read its status, percent complete and errors
  • wait on it properly in scripts

Tip

Work request errors often hold the real cause: an out-of-capacity condition, a quota, a missing policy or a conflicting operation. Read them before you retry. Blind retries can queue up conflicting requests.

Which command group to use

Work requests are not one global list. Each service exposes its own, and the CLI groups differ.

Service List command Notes
Compute and other Core operations oci work-requests work-request list Generic Work Requests API
OKE clusters and node pools oci ce work-request list Filters for cluster, resource type and status
Load Balancer oci lb work-request list Scoped to one load balancer
Connector Hub oci sch work-request list
MySQL HeatWave oci mysql work-request list
Other services oci <service> work-request --help Many services have their own group. Names vary by service and CLI version

If you're not sure, run oci <service> --help and look for work-request. Resource Manager is different: it uses jobs (oci resource-manager job), not work requests.

Generic work requests (Compute and Core)

List recent work requests in a compartment

C=ocid1.compartment.oc1..aaaa...

oci work-requests work-request list -c "$C" --all \
  --query 'data[].{op:"operation-type",status:status,pct:"percent-complete",accepted:"time-accepted",id:id}' \
  --output table

The generic list has no --status or --sort-by filter. Filter in JMESPath instead:

# Only failed work requests
oci work-requests work-request list -c "$C" --all \
  --query 'data[?status==`FAILED`].{op:"operation-type",accepted:"time-accepted",id:id}' \
  --output table

Status values are typically ACCEPTED, IN_PROGRESS, SUCCEEDED, FAILED, CANCELING and CANCELED. Check your own output for the exact strings.

Find the work request for one resource

INSTANCE=ocid1.instance.oc1..aaaa...

oci work-requests work-request list -c "$C" --resource-id "$INSTANCE" --all \
  --query 'data[].{op:"operation-type",status:status,id:id}' --output table

Get details, errors and log entries

WR=ocid1.coreservicesworkrequest.oc1..aaaa...   # OCID prefix varies by service

# Status, percent complete and the resources it touched
oci work-requests work-request get --work-request-id "$WR"

# The error messages - start here when status is FAILED
oci work-requests work-request-error list --work-request-id "$WR" --all \
  --query 'data[].{code:code,message:message,time:timestamp}' --output table

# Step-by-step log of what the service did
oci work-requests work-request-log-entry list --work-request-id "$WR" --all \
  --sort-order ASC --query 'data[].{time:timestamp,msg:message}' --output table

The generic group has no cancel command. To stop an operation, use the resource's own API where one exists, or let it finish and reverse the change.

OKE work requests

OKE has richer filters, so use them:

CLUSTER=ocid1.cluster.oc1..aaaa...

# Failed node pool operations on one cluster
oci ce work-request list -c "$C" --cluster-id "$CLUSTER" \
  --resource-type NODEPOOL --status FAILED \
  --sort-by TIME_ACCEPTED --sort-order DESC --output table

# Errors and logs for one of them
oci ce work-request-error list --work-request-id "$WR"
oci ce work-request-log-entry list --work-request-id "$WR"

--resource-type takes CLUSTER or NODEPOOL. You can pass --status more than once, for example --status IN_PROGRESS --status ACCEPTED, to see what is still running.

Warning

Starting a second node pool update or upgrade while one is IN_PROGRESS usually fails or queues behind it. Check for in-flight work requests before you retry a cluster or node pool change.

Load Balancer work requests

Every listener, backend set, certificate or backend change on a load balancer is a work request. Changes to one load balancer apply one after another, so a stuck or failed one explains why later changes "don't apply".

LB=ocid1.loadbalancer.oc1..aaaa...

oci lb work-request list --load-balancer-id "$LB" --all \
  --query 'data[].{type:type,state:"lifecycle-state",msg:message,accepted:"time-accepted",id:id}' \
  --output table

oci lb work-request get --work-request-id "$WR" --query 'data."error-details"'

Field names here differ from the generic API (lifecycle-state instead of status). Run one command without --query first to see the shape in your CLI version.

Common errors and what they mean

Error text (paraphrased) Cause Fix
Out of host capacity No capacity for that shape in the AD or fault domain Try another AD or fault domain or a flex shape size, or use a capacity reservation
LimitExceeded / QuotaExceeded Service limit or compartment quota reached Raise the limit or quota, or free capacity
Conflict / resource busy Another operation is running on the same resource Wait for the in-flight work request, then retry
NotAuthorizedOrNotFound inside the error The service lacks a policy on a dependent resource (subnet, key, image) Add the missing policy and check the dependent OCID and its compartment
Image or shape not compatible Image doesn't support the shape (for example, x86 image on Arm) Pick a compatible image and shape pair

Waiting on work in scripts

Don't poll the resource state in a tight loop. Use the CLI's built-in waiters. Most create and update commands accept --wait-for-state and wait on the work request or the resource:

oci compute instance action --instance-id "$INSTANCE" --action SOFTRESET \
  --wait-for-state RUNNING --max-wait-seconds 900 --wait-interval-seconds 15

Some commands wait on the work request itself and accept states like SUCCEEDED and FAILED. Check the command's --help to see which states it accepts. If a waiter times out, the CLI exits non-zero. The work request may still be running, so look it up before you retry.

A simple polling fallback for any generic work request:

while :; do
  S=$(oci work-requests work-request get --work-request-id "$WR" --query 'data.status' --raw-output)
  echo "$(date -u +%T) $S"
  case "$S" in SUCCEEDED) break ;; FAILED|CANCELED)
    oci work-requests work-request-error list --work-request-id "$WR" --all; exit 1 ;; esac
  sleep 20
done

PowerShell equivalent

$C = "ocid1.compartment.oc1..aaaa..."
oci work-requests work-request list -c $C --all | ConvertFrom-Json |
  Select-Object -ExpandProperty data |
  Where-Object { $_.status -eq 'FAILED' } |
  Select-Object 'operation-type', 'time-accepted', id

Prevent it next time

  • In automation, always capture the opc-work-request-id (shown in --debug output and returned by many commands). Log it next to the resource OCID so you can trace the failure later.
  • Make scripts fail loudly. After a waiter or poll loop ends in FAILED, print work-request-error list before exiting.
  • Check for in-flight work requests before a change on OKE node pools and load balancers, so you don't stack conflicting operations.
  • Use OCI Audit to see who started an operation. Use work requests to see what happened to it.