Claude
Skills
Sign in
Back

oraclecloud-common-errors

Included with Lifetime
$97 forever

Diagnose and fix Oracle Cloud Infrastructure API errors with real error codes and proven fixes. Use when encountering OCI ServiceError exceptions, auth failures, SSL issues, or timeout errors. Trigger with "oci error", "fix oraclecloud", "debug oci", "NotAuthorizedOrNotFound", "oci 401".

Backend & APIssaasoraclecloudoci

What this skill does

# Oracle Cloud Common Errors

## Overview

OCI API errors are notoriously cryptic. `NotAuthorizedOrNotFound` (404) could mean an IAM policy is missing **or** you typed the OCID wrong — the error is intentionally ambiguous for security. `NotAuthenticated` (401) covers six different config file problems. `CERTIFICATE_VERIFY_FAILED` has different fixes depending on your SDK language, OS, and whether you are behind a corporate proxy.

**Purpose:** A diagnostic decoder ring mapping every common OCI error to its real root cause and fix, with runnable diagnostic commands for each scenario.

## Prerequisites

- An OCI account with `~/.oci/config` configured (see `oraclecloud-install-auth`)
- **Python 3.8+** with `pip install oci` installed
- **OCI CLI** installed (`pip install oci-cli`) for diagnostic commands

## Instructions

### Authentication Errors (401 NotAuthenticated)

The 401 error has six distinct root causes. Run this diagnostic to isolate which one:

```python
import oci
import os

def diagnose_auth():
    """Diagnose OCI 401 NotAuthenticated errors."""
    config_path = os.path.expanduser("~/.oci/config")

    # Check 1: Config file exists
    if not os.path.exists(config_path):
        return "CAUSE: Config file missing. Run: oci setup config"

    config = oci.config.from_file(config_path)

    # Check 2: All required fields present
    required = ["user", "fingerprint", "tenancy", "region", "key_file"]
    for field in required:
        if field not in config or not config[field]:
            return f"CAUSE: Missing field '{field}' in ~/.oci/config"

    # Check 3: Key file exists
    key_path = os.path.expanduser(config["key_file"])
    if not os.path.exists(key_path):
        return f"CAUSE: Key file not found: {key_path}"

    # Check 4: Key is private (not public)
    with open(key_path, "r") as f:
        first_line = f.readline().strip()
    if "PUBLIC" in first_line:
        return "CAUSE: key_file points to PUBLIC key. Use the private key (no _public suffix)"

    # Check 5: Key file permissions
    perms = oct(os.stat(key_path).st_mode)[-3:]
    if perms != "600":
        return f"CAUSE: Key permissions are {perms}. Run: chmod 600 {key_path}"

    # Check 6: Fingerprint matches
    return "Config looks valid. Fingerprint mismatch? Verify in Console > User Settings > API Keys"

print(diagnose_auth())
```

**401 Root Cause Table:**

| Symptom | Root Cause | Fix |
|---------|-----------|-----|
| `did not find a proper configuration for user` | Missing or malformed `~/.oci/config` | Recreate with `oci setup config` |
| `could not find private key` | `key_file` path wrong or file missing | Check path; key must exist at that location |
| `private key does not match` | Fingerprint in config does not match uploaded public key | Upload correct public key or regenerate pair |
| `key_file points to public key` | `key_file=~/.oci/oci_api_key_public.pem` | Change to `key_file=~/.oci/oci_api_key.pem` (private key) |
| `permission denied reading key` | Key file permissions too open | `chmod 600 ~/.oci/oci_api_key.pem` |
| `InvalidKeyId` | User OCID or tenancy OCID wrong | Verify OCIDs in Console > Profile > User Settings |

### Authorization Errors (404 NotAuthorizedOrNotFound)

This is the most confusing OCI error. A 404 means **either** the resource does not exist **or** you lack IAM permission to see it. OCI hides the distinction intentionally.

**Diagnostic steps:**

```bash
# Step 1: Verify the OCID format is correct
echo "ocid1.instance.oc1.iad.aaaa..." | grep -P '^ocid1\.\w+\.oc1\.'

# Step 2: Verify you can list resources in the compartment
oci compute instance list --compartment-id <COMPARTMENT_OCID> --limit 1

# Step 3: Check IAM policies affecting your user
oci iam policy list --compartment-id <TENANCY_OCID> --all \
  --query "data[?contains(statements[0], 'instances')]"
```

**Common IAM policy fixes:**

```
# Allow a group to manage compute in a compartment
allow group Developers to manage instances in compartment MyCompartment

# Allow a group to read all resources (useful for debugging)
allow group Developers to read all-resources in tenancy
```

### SSL Certificate Errors (CERTIFICATE_VERIFY_FAILED)

```python
# Diagnostic: check which CA bundle Python uses
import ssl
print(ssl.get_default_verify_paths())

# Fix 1: Install/update certifi
# pip install --upgrade certifi

# Fix 2: Point to system CA bundle (Linux)
import os
os.environ["REQUESTS_CA_BUNDLE"] = "/etc/ssl/certs/ca-certificates.crt"

# Fix 3: Corporate proxy — add proxy CA to certifi bundle
# cat proxy-ca.pem >> $(python -c "import certifi; print(certifi.where())")
```

**SSL Fix by Environment:**

| Environment | Fix |
|------------|-----|
| Linux (system Python) | `pip install --upgrade certifi` |
| macOS | `brew install ca-certificates` + update certifi |
| Corporate proxy | Add proxy CA cert to certifi bundle |
| Docker container | Copy CA bundle: `COPY ca-bundle.crt /etc/ssl/certs/` |
| Air-gapped | Set `REQUESTS_CA_BUNDLE` to local CA file |

### Rate Limit Errors (429 TooManyRequests)

OCI does **not** send a `Retry-After` header. You must implement your own backoff:

```python
import oci
import time
import random

def handle_rate_limit(fn, max_retries=5):
    """Handle OCI 429 errors. No Retry-After header — use jittered backoff."""
    for attempt in range(max_retries):
        try:
            return fn()
        except oci.exceptions.ServiceError as e:
            if e.status == 429:
                delay = (2 ** attempt) + random.uniform(0, 2)
                print(f"Rate limited. Waiting {delay:.1f}s (attempt {attempt + 1})")
                time.sleep(delay)
            else:
                raise
    raise RuntimeError("Rate limit retries exhausted")

# Or use the built-in strategy
compute = oci.core.ComputeClient(
    config, retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY
)
```

### Timeout Errors (ServiceError status -1)

A `ServiceError` with `status == -1` means the SDK timed out before the server responded:

```python
import oci

config = oci.config.from_file("~/.oci/config")

# Default has NO connection timeout. Always set both:
compute = oci.core.ComputeClient(
    config,
    timeout=(10, 60)  # (connect_timeout, read_timeout)
)

# Object Storage uploads need longer read timeout
object_storage = oci.object_storage.ObjectStorageClient(
    config,
    timeout=(10, 600)  # 10 min for large uploads
)
```

### Internal Server Errors (500 InternalError)

```python
import oci

# Check OCI service health first
# https://ocistatus.oraclecloud.com

# 500 errors are transient — use retry strategy
compute = oci.core.ComputeClient(
    oci.config.from_file("~/.oci/config"),
    retry_strategy=oci.retry.DEFAULT_RETRY_STRATEGY  # Retries 500, 502, 503, 504
)
```

## Output

After working through this diagnostic guide you will have:

- Identified the exact root cause of your OCI error from the error code and message
- A runnable diagnostic script for 401 auth errors that checks all six failure modes
- IAM policy statements to resolve 404 authorization errors
- Correct timeout and retry configuration for 429 and 500 errors
- SSL certificate fixes for your specific environment

## Error Handling

**Complete OCI Error Reference Table:**

| Error | Status | Exception | Root Cause | Fix |
|-------|--------|-----------|-----------|-----|
| NotAuthenticated | 401 | `ServiceError` | Wrong config, key, or fingerprint | Run `diagnose_auth()` above |
| NotAuthorizedOrNotFound | 404 | `ServiceError` | Missing IAM policy OR wrong OCID | Check OCID format, then IAM policies |
| TooManyRequests | 429 | `ServiceError` | Rate limit exceeded | Backoff with jitter (no Retry-After header) |
| InternalError | 500 | `ServiceError` | OCI service error | Retry; check https://ocistatus.oraclecloud.com |
| Timeout | -1 | `ServiceError` | No response in time | Set `timeout=(connect, read)` on client |
| CERTIFICATE_VERIFY_FAILED | — | `SSLError` | CA bundle outdated or proxy | Update cert

Related in Backend & APIs