detail, and the SDK surfaces it as QCOSCloudError.reason. Nothing is ever
charged on a rejection — refusals happen before credit is reserved, or the
reservation is released.
{ "detail": "insufficient_credits" }
Workload refusal reasons
Returned byPOST /api/v1/platform/execution/jobs (and surfaced by
qc.run(), qcoscloud run/gpu/cpu):
| Reason | HTTP | Meaning | What to do |
|---|---|---|---|
insufficient_credits | 402 | The prepaid balance cannot cover the run’s worst-case estimate | Top up credits or lower shots/runtime |
max_cost_exceeded | 402 | The estimate exceeds your max_estimated_cost_usd | Raise the cap or shrink the run |
max_charge_below_estimate | 402 | max_actual_charge_usd was set below the estimate | Set it at or above the estimate (it is an overrun shield, not a discount) |
daily_budget_exceeded | 402 | The workspace’s rolling daily execution budget would be exceeded | Wait for the window to roll, or have an owner/admin raise the budget |
monthly_budget_exceeded | 402 | The workspace’s rolling monthly execution budget would be exceeded | Same as above |
max_shots_exceeded | 422 | shots exceeds your max_shots guardrail | Lower shots or raise the guardrail |
runtime_bound_required | 422 | The target bills per minute/second and needs max_runtime_seconds | Pass a runtime bound (minutes= in the SDK helpers) |
quantum_circuit_missing | 422 | A QUANTUM_CIRCUIT workload carried neither qasm nor artifact_uri | Pass your OpenQASM circuit — see Run workloads |
invalid_execution_mode | 422 | execution_mode is not NATIVE or QCOS_OPTIMIZED | Fix the mode |
qcos_license_required | 403 | QCOS_OPTIMIZED requires an active QCOS license | Run NATIVE, or license QCOS for the workspace |
no_active_entitlement_for_offer | 404 | The target is not activated for your workspace | List targets first (activates the default catalog); QPU devices need an entitlement |
not_workspace_member | 403 | The caller is not a member of the workspace | Use a key/session belonging to the workspace |
instance_not_found | 404 | Unknown or deleted instance_id | Check qc.instances() |
instance_target_not_allowed | 403 | The instance’s allowlist does not include this target | Use another instance or extend the allowlist |
instance_access_denied | 403 | You are not in the instance’s access group | Ask an owner/admin, or use an instance you can access |
free_plan_simulators_only | 403 | A free instance was pointed at real hardware | Use a prepaid instance for QPUs |
free_plan_limit_met | 403 | The free instance’s 10 min/month cap is reached (nothing charged) | Wait for next month or switch to prepaid |
free_cpu_limit_met | 403 | The free CPU-simulation allowance (10 min/month) is exhausted | Use the paid cpu.* tiers |
paygo_not_released | 403 | Pay-as-you-go is not approved for this workspace | Request paygo; prepaid works meanwhile |
gpu_provider_unavailable | 503 | GPU/CPU capacity is not currently available — fails closed, no money held | Retry later, or contact SoftQuantus |
unknown_target_unpriced | 400 | The target cannot be priced — refused rather than guessed | Check the target id against the catalog |
conflict | 409 | Idempotency-key collision that could not be replayed | Use a fresh Idempotency-Key |
Evidence and job lookup
| Reason | HTTP | Meaning | What to do |
|---|---|---|---|
evidence_not_available_until_settled | 409 | The job has not settled yet | Poll until status: "SETTLED", then fetch evidence |
not_found (in the body, HTTP 200) | 200 | GET /execution/jobs/{id} for an unknown/foreign job returns a body with "status": "not_found" | Check the status field, not just the HTTP code |
Instance and pay-as-you-go management
| Reason | HTTP | Meaning |
|---|---|---|
invalid_plan | 422 | Plan must be free, prepaid or paygo |
free_instance_exists | 409 | Only one free instance per workspace |
already_approved | 409 | Paygo is already released — no request needed |
request_pending | 409 | A paygo request is already awaiting review |
staff_only | 403 | Paygo review endpoints are for SoftQuantus staff |
Generic HTTP semantics
| Status | When you see it |
|---|---|
| 401 | Missing/invalid/revoked API key (Invalid API key), or an expired console session |
| 403 | Not an active member of the workspace, a role without the needed permission (e.g. developer on billing actions, viewer on execution), or a console request failing CSRF validation |
| 404 | Unknown resource (key, member, invitation, instance) |
| 409 | Conflicts: duplicate signup email, member already in workspace, idempotency collision |
| 422 | Request validation failed (Pydantic field errors, or a reason from the tables above) |
| 429 | Per-IP rate limit exceeded — default 60 requests/minute (10/minute on auth endpoints). Body: {"detail": {"code": "rate_limit_exceeded", "message": "Too many requests. Limit: 60/minute."}}. Back off and retry |
| 502 | An upstream (e.g. the QCOS runtime behind the proxy) returned an error or was unreachable |
| 503 | Fail-closed refusal (gpu_provider_unavailable) or an upstream in a known-unconfigured state |
Handling errors in code
from qcoscloud import QCOSCloud, QCOSCloudError
qc = QCOSCloud()
try:
job = qc.gpu_job(gpu="h100", command="python train.py", minutes=120)
except QCOSCloudError as e:
if e.reason == "insufficient_credits":
print("Top up:", qc.add_credits_url())
elif e.reason == "gpu_provider_unavailable":
print("No capacity right now — nothing was charged; retry later.")
else:
raise
error: ... <reason>. <hint>) and
exits 1; a missing API key exits 2.