Errors are machine-readable: the response body carries a stable reason in 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.
Branch on the reason string, never on human-readable text.

Workload refusal reasons

Returned by POST /api/v1/platform/execution/jobs (and surfaced by qc.run(), qcoscloud run/gpu/cpu):

Evidence and job lookup

Instance and pay-as-you-go management

Generic HTTP semantics

Handling errors in code

The CLI prints the same reasons on stderr (error: ... <reason>. <hint>) and exits 1; a missing API key exits 2.