The SDK raises typed exceptions instead of returning error dicts. All inherit from SdkError so you can catch broadly or narrowly.
from yourbot_sdk import (
SdkError, CapabilityError, RateLimitError, DiscordApiError,
SdkPermissionError, ValidationError, KvQuotaError, RpcTimeoutError,
)
@plugin.on_event("message_create")
def on_message(ctx: Context, event: dict):
try:
ctx.discord.send_message(channel_id=event["channel_id"], content="Pong")
except RateLimitError as exc:
ctx.log(f"rate limited; retry in {exc.retry_after}s", level="warning")
except SdkPermissionError as exc:
ctx.log(f"missing Discord permission: {exc}", level="error")
except DiscordApiError as exc:
if exc.status_code == 404:
ctx.log("channel was deleted", level="info")
else:
ctx.log(f"discord {exc.status_code}: {exc}", level="error")
except SdkError as exc:
# Catch-all - logs and keeps the plugin running.
ctx.log(f"unexpected: {exc}", level="error")
Every exception also carries a stable machine-readable .code so you can branch on failures without string-matching: v0.6.1
except SdkError as e:
if e.code == "RATE_LIMITED":
time.sleep(getattr(e, "retry_after", 5))
elif e.code == "CAPABILITY_DENIED":
ctx.log(f"missing capability: {e}", level="error")
Reference
| Exception | Raised when |
|---|---|
| SdkError | Base class — catch this to handle anything from the SDK. SDK_ERROR |
| CapabilityError | You called an API your plugin didn't request via capabilities_required. CAPABILITY_DENIED |
| RateLimitError | Quota exceeded. Has .retry_after (seconds). RATE_LIMITED / QUOTA_EXCEEDED |
| DiscordApiError | Discord's REST returned non-2xx. Has .status_code. DISCORD_API_ERROR |
| SdkPermissionError | Bot is missing a Discord guild permission — the message names it, and from v0.8.5 .permission carries the permission name (empty string when unknown). BOT_MISSING_PERMISSION |
| ValidationError | You passed invalid args (empty channel_id, bad emoji, key with null bytes…). VALIDATION_ERROR |
| KvQuotaError | Hit a KV key-count quota (50k per server or 500k global). An oversized value or key currently surfaces as a generic RPC error instead. KV_QUOTA_EXCEEDED |
| RpcTimeoutError | The runner didn't respond inside the per-call timeout. RPC_TIMEOUT |
| RpcError v0.8.5 | Any host error that maps to nothing more specific. Also subclasses RuntimeError, which is what these errors were raised as before v0.8.5. RPC_ERROR |
| PermissionError alias | Backwards-compatible alias for SdkPermissionError. |
| TimeoutError alias | Backwards-compatible alias for RpcTimeoutError. |