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/configconfigured (seeoraclecloud-install-auth) - Python 3.8+ with
pip install ociinstalled - 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:
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:
# 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)
# 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:
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:
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)
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 certifi or set REQUESTS_CA_BUNDLE |
| InvalidParameter | 400 | ServiceError | Malformed request body | Check OCID format and required fields |
| Out of host capacity | 500 | ServiceError | No hosts available (ARM shapes) | Retry loop; see oraclecloud-hello-world |
Examples
One-command connectivity test:
# Tests auth + network + SSL in one call
oci iam region list --output table 2>&1 || echo "FAILED — run oraclecloud-common-errors diagnostic"
Catch-all error handler for scripts:
import oci
import sys
config = oci.config.from_file("~/.oci/config")
compute = oci.core.ComputeClient(config)
try:
compute.list_instances(compartment_id=config["tenancy"])
print("OK")
except oci.exceptions.ServiceError as e:
print(f"OCI Error: {e.status} {e.code}")
print(f"Message: {e.message}")
print(f"Request ID: {e.request_id}") # Include this in support tickets
if e.status == 401:
print("ACTION: Check ~/.oci/config — see oraclecloud-install-auth")
elif e.status == 404:
print("ACTION: Verify OCID and IAM policies — see 404 section above")
elif e.status == 429:
print("ACTION: Rate limited — implement backoff")
elif e.status == -1:
print("ACTION: Timeout — increase client timeout values")
sys.exit(1)
except oci.exceptions.ConfigFileNotFoundError:
print("ACTION: ~/.oci/config not found. Run: oci setup config")
sys.exit(1)
Resources
- OCI SDK Troubleshooting — official error resolution guide
- OCI Known Issues — active bugs and workarounds
- OCI Status Page — real-time service health dashboard
- OCI API Reference — error response schemas per service
- OCI Python SDK Reference — exception class hierarchy
- OCI IAM Policies — policy syntax for 404 fixes
Next Steps
Once errors are resolved, see oraclecloud-sdk-patterns for retry and timeout patterns to prevent errors proactively, or oraclecloud-local-dev-loop for a productive development workflow with fast feedback.