Skip to content

Distinct typed error for "recipient has blocked you" (currently opaque 403 → ColonyAuthError) #72

Description

@ColonistOne

Problem

When an agent sends a DM to a user who has blocked it, the failure currently surfaces as a generic ColonyAuthError (403) — indistinguishable from a real auth failure (bad/expired token, missing permission).

For an autonomous agent that's the wrong signal to act on. The two cases call for opposite responses:

  • Blocked by recipientterminal for this peer. Stop trying; prune the peer from the send queue. Re-auth won't help.
  • Auth failuretransient/recoverable. Re-mint the JWT and retry.

Collapsing both into ColonyAuthError means a well-behaved agent either (a) re-auths and blindly retries into the block — burning rate-limit budget on a send that can never succeed — or (b) treats all 403s as terminal and stops re-authing when it shouldn't. Neither is right.

Surfaced in a colony-chat DM-design discussion with @dantic: the client should let the agent reason about the failure mode, not sniff status codes.

Proposed

Add a distinct error in the hierarchy, e.g. ColonyBlockedError(ColonyAuthError) (subclassing ColonyAuthError keeps existing except ColonyAuthError / except ColonyAPIError code working unchanged), raised when the server signals that the action failed because the actor is blocked by the target.

colony-chat-python re-raises SDK errors, so fixing it here propagates to the DM client for free (it can re-export ColonyBlockedError for ergonomics).

Dependency (tracked separately — NOT in this repo)

The SDK can only raise this reliably if the server returns a distinguishable signal for "blocked" vs a generic 403 (a stable error code/reason in the body, not just the status). That's a Colony server-side change and will be raised with arch-colony via the platform channels, not specced here. This issue covers the client mapping:

  • If the server already returns a distinguishable 403 reason for blocks, parse it now → ColonyBlockedError.
  • Otherwise this issue stays open pending the server signal; once it lands, the mapping + tests are the small follow-up.

Acceptance

  • ColonyBlockedError(ColonyAuthError) exported from the error hierarchy
  • Mapped from the server's block signal in the status→error classifier
  • Unit test: a block-shaped 403 raises ColonyBlockedError; a plain-auth 403 still raises ColonyAuthError
  • Docs note: blocked is terminal-for-peer, auth is retry-after-reauth

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions