# `unprocessable`: Refused by current state

> HTTP 422. The request is well formed, and the current state of what it addresses refuses it. The message says what is in the way.

Every value in the request is legal, and the thing it acts on is not in a state that allows it: an article that has already been sent, a newsletter with no verified sending address, a slug another article already uses. Changing the request's syntax will not help. Changing the state will, or choosing a different target.

Most of these come from the article lifecycle (`POST /articles/{article}/send`, `/schedule`, `/unschedule`, `/test-send`, and `PATCH /articles/{article}`) and from tags. `param` is set when one field is responsible (`slug`, `name`, `tag`, `attempt`). The message always says what state is in the way, and nothing was changed.

A newsletter that is published through another provider has its own code, `not_commune_newsletter`.

## Why it happens, and how to fix it

### 1. The newsletter cannot send yet

Sending, scheduling and test sends need a sending address. The newsletter has none, or its address is not verified yet (the message gives the verification state).

**Fix:** Add or verify the sending address on the newsletter's [Domains](https://usecommune.com/dashboard/domains) page in the Commune dashboard. `GET /newsletters/{newsletter}/senders` and `GET /senders/{sender}` report each address's state and the DNS records that complete verification.

### 2. The article cannot be sent as it is

The send and schedule gates refused the article's body. It is empty. Or it is missing the unsubscribe link, the mailing address (`{{ address }}`), or both, which commercial email must carry; Commune seeds them into every draft and this gate cannot be bypassed. Or an image in it could not be loaded, which would break it for every recipient (an image host that is only slow is never reported).

**Fix:** Put content in the body (`content_markdown` on `PATCH /articles/{article}`). Restore the unsubscribe link and mailing address that were edited out of the footer. For images, re-upload or remove the ones the message lists, or send again with `{"acknowledge_broken_images": true}` in the body if you accept them broken.

### 3. The article is in the wrong state

Only a draft, a scheduled article or one whose last send failed can be sent or scheduled; one that is sending, sent or archived cannot. `POST /articles/{article}/unschedule` needs an article that is scheduled. `PATCH /articles/{article}` refuses an article that is sending (wait for it to finish), sent (an email cannot be recalled), archived (unarchive it in Commune first), or imported from the newsletter's provider (it can never be edited here).

**Fix:** Read the article with `GET /articles/{article}` and check `status` and `is_imported`, then act on what it says. To send the same content again, create a new article.

### 4. The state changed during the request, or the time has passed

The article moved between the check and the change, usually because another request sent or scheduled it at the same moment. On `POST /articles/{article}/schedule`, a `scheduled_for` in the past is refused the same way rather than sent immediately.

**Fix:** Read the article again and decide from its current `status`. For scheduling, send a `scheduled_for` in the future, in UTC or with an explicit offset.

### 5. A slug or tag name is already taken

Article slugs are unique within a newsletter, and tag names are unique among a newsletter's live tags. `param` is `slug` or `name`.

**Fix:** Choose another value. For an article, you can leave `slug` out and Commune derives a free one from the title.

### 6. The tag is retired

A tag that was deleted after an article was sent to it is kept as retired, because it still decides who may read that article. A retired tag cannot be renamed or added to anyone new (`param` is `name` or `tag`). Removing it from a subscriber still works.

**Fix:** Create a new tag with `POST /newsletters/{newsletter}/tags` and use that instead. `GET /tags/{tag}` shows whether a tag is retired.

### 7. Other refusals with a clear target

`POST /threads/{thread}/publish` was given the id of a reply rather than a thread. `POST /delivery-attempts/{attempt}/replay` was asked to redeliver to a destination that is switched off (`param` is `attempt`). A test send was refused by the sending service for a reason the message quotes.

**Fix:** Publish the thread the reply belongs to (its id is the `thread` on the message). Enable the destination in the delivery portal, which `POST /newsletters/{newsletter}/portal-session` opens, then replay. For a test send, act on the reason in the message.

## Retrying

No: the same request is refused until the state it names changes, so fix that state (or pick another target) and then send it again, with the same `Idempotency-Key` if you like, since nothing was changed.

## Example response

```json
{
  "error": {
    "code": "unprocessable",
    "message": "This newsletter's sending address is not verified, so no email can go out from it. Its verification is `pending`. The DNS records that finish verification are on the sender, which the `senders` operations return.",
    "request_id": "req_01j9c8h1q7m3n4p5r6s7t8u9v0",
    "docs_url": "https://usecommune.dev/errors/unprocessable"
  }
}
```

Often confused with: [`not_commune_newsletter`](https://usecommune.dev/errors/not_commune_newsletter.md), [`bad_request`](https://usecommune.dev/errors/bad_request.md), [`conflict`](https://usecommune.dev/errors/conflict.md).
