Sume 429: read error.details.scope, and rate_limit_unavailable

A Sume 429 names the budget in error.details.scope and gives retry_after_seconds. A degraded rate_limit_unavailable 429 is a different case. Python handler.

4 min readSume
All posts

Three different 429s

A Sume 429 is not one thing. rate_limited means your key spent its per-minute budget. queue_full means the workspace has no accepted generation capacity left. And rate_limit_unavailable means the rate limiter itself is degraded and Sume cannot count your requests right now.

Each wants a different reaction, and the error body tells you which: error.code first, then error.details.

What rate_limited carries

From the API source, a rate_limited body has details.limit, remaining (0), scope, window_seconds and retry_after_seconds. The scope is read or write. The retry-after header carries the same wait in seconds. Because reads and writes have separate budgets, a read-scope 429 on a status poll tells you your submits are untouched.

429 variants, from Sume docs and API source read 2026-10-05
error.codeMeaningReaction
rate_limitedPer-key budget spent, scope read or writeSleep retry-after, then resume
queue_fullWorkspace accepted-job capacity fullWait for jobs to finish or cancel queued ones
rate_limit_unavailableRate limiting degradedRetry later; nothing you did caused it

A handler you can run

This function takes the status and the raw body and returns the decision. It sleeps nothing itself, so you can unit-test it.

import json

def decide(status, body):
    if status != 429:
        return ("other", 0)
    err = json.loads(body).get("error", {})
    d = err.get("details") or {}
    wait = d.get("retry_after_seconds") or 5
    code = err.get("code")
    if code == "queue_full":
        return ("drain-queue", 0)
    if code == "rate_limit_unavailable":
        return ("retry-later", wait)
    return ("sleep-" + str(d.get("scope", "unknown")), wait)

sample = '{"error":{"code":"rate_limited","details":{"scope":"read","retry_after_seconds":12}}}'
print(decide(429, sample))

Retry safety

Do not retry a paid submit after a 429 without an Idempotency-Key. With the same key, a retry returns the original job instead of billing a second one. For queue_full, the docs say to retry with the same key after capacity opens.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume