> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting: IVR NLU intent catalogue authoring rejections

> Decode the rejections the NLU intent-catalogue endpoints return when you create, update, or delete catalogue intents — IVR_NLU_CATALOGUE_FULL, IVR_NLU_NAME_CONFLICT, IVR_NLU_CREATE_ERROR, IVR_NLU_NOT_FOUND — and clear each one without losing authoring work.

# Troubleshooting: IVR NLU intent catalogue authoring rejections

The intent catalogue is where you author the named intents and example
utterances your conversational IVR classifies against. Writes to it —
creating an intent, renaming one, deleting one — can be rejected with
four codes that are entirely about **your request**, not about the
model layer. This page decodes each code, the change that clears it,
and how these authoring-time rejections differ from the runtime 503s
the classifier throws on live calls.

## Authoring rejections are not runtime 503s

Two different failure families share the NLU surface:

* **Authoring-time rejections (this page).** Returned by the catalogue
  endpoints under `/api/v1/voice/ivr-nlu-hints` when a create, update,
  or delete cannot be applied: a full catalogue, a name already taken,
  a stale id. They are deterministic — the same request gets the same
  rejection until you change it — and the model layer is fine.
* **Runtime 503s** — `IVR_CLASSIFY_LLM_ERROR` and
  `IVR_SLOT_EXTRACT_LLM_ERROR` — hit live calls when the classifier or
  slot-extractor leg goes down. The catalogue is fine; the model call
  is not. Recovery for those (re-prompt, DTMF fallback, queue) lives on
  [IVR NLU classifier and slot-extraction failures](https://docs.orbit.devotel.io/troubleshooting/ivr-nlu-llm-failures.md).

If a 503 lands while you are authoring, or a catalogue code appears on
a live call, you want the other page of the pair.

## The catalogue write rejections

| Code | Status | When it returns | Fix |
| - | - | - | - |
| `IVR_NLU_CATALOGUE_FULL` | 422 | The catalogue already holds 64 intents, the per-tenant cap. | List the catalogue, delete an intent you no longer branch on; each delete frees one slot. |
| `IVR_NLU_NAME_CONFLICT` | 409 | An intent with that name already exists — names are unique per tenant. | Rename the new intent, or update the existing one instead of re-posting the create. |
| `IVR_NLU_CREATE_ERROR` | 500 | The insert failed for a reason other than a name conflict. | Retry once with the same body; if it persists, escalate with the envelope's `request_id`. |
| `IVR_NLU_NOT_FOUND` | 404 | The id in your update or delete no longer exists — usually a stale id captured before a delete. | Re-list the catalogue and use a current id. |

### `IVR_NLU_CATALOGUE_FULL` — the 64-intent cap

A tenant catalogue holds at most 64 intents. The cap is checked before
the insert, so a rejected create writes nothing partial. To free a
slot, list the catalogue (`GET /api/v1/voice/ivr-nlu-hints`) and delete
an intent your flows no longer reference — deletion is the only way to
release a slot, so prefer deleting intents that are truly retired over
ones you might tune later. If you are close to the cap because many
intents cover one menu, consider merging intents whose descriptions
phrase the same middle ground; the
[routing guide](https://docs.orbit.devotel.io/guides/ivr-routing-nlu.md) covers description craft.

### `IVR_NLU_NAME_CONFLICT` — names are unique per tenant

Intent names are lowercase alphanumeric with hyphens or underscores,
max 64 characters, unique per tenant — the same handle rules the
[routing guide](https://docs.orbit.devotel.io/guides/ivr-routing-nlu.md#2-model-your-intents) teaches.
Re-posting a create with a name that already exists returns this 409,
which commonly bites scripts that retry a create after a network
error: the first attempt may have succeeded. List the catalogue, find
the existing intent, and `PATCH` its description or utterances instead
of posting the create again. A `PATCH` that keeps an intent's own name
never conflicts; only renaming onto another intent's name does.

### `IVR_NLU_CREATE_ERROR` — retry once, then escalate

A 500 on create means the write failed for a non-conflict reason —
transient by design of the code, unlike the deterministic 422 and 409
above. Retry once with an identical body; a create writes nothing
until it succeeds, so the retry cannot double-insert. If the second
attempt also returns `IVR_NLU_CREATE_ERROR`, escalate with the
`request_id` the error envelope carries.

### `IVR_NLU_NOT_FOUND` — stale id on update or delete

Ids are stable for the life of an intent, but a delete removes them
outright. A script or dashboard tab holding an id from an earlier
session 404s once another writer deletes that intent. Re-list the
catalogue before batching updates or deletes, and treat
`IVR_NLU_NOT_FOUND` on a delete as already-done rather than an error.

## Malformed payloads return `VALIDATION_ERROR`

A name with uppercase letters or spaces, an empty utterance, an
utterance over 100 characters, or more than 16 utterances on one
intent does not return a catalogue code — it comes back as the generic
`VALIDATION_ERROR` 422 with a `details` map naming the offending
field. Fix the field and resend; the catalogue codes above only return
for well-formed requests the catalogue itself refuses.

## See also

* [IVR NLU classifier and slot-extraction failures](https://docs.orbit.devotel.io/troubleshooting/ivr-nlu-llm-failures.md)
* [Build an IVR flow with NLU intent routing](https://docs.orbit.devotel.io/guides/ivr-routing-nlu.md)
* [IVR intents endpoint reference](https://docs.orbit.devotel.io/voice/ivr-intents.md)
* [LLM timeouts and upstream failures](https://docs.orbit.devotel.io/troubleshooting/llm-upstream-failures.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.