> For the complete documentation index, see [llms.txt](https://engineering.umh.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://engineering.umh.app/engineering/development-process/how-to-build/coding-standards/architecture/error-management.md).

# Error management

How errors and warnings reach the person who can act on them.

Owner: Jeremy

We decide on purpose what happens with every error: who has to act on it, where it shows up, and what we show the user.

## Rules

* An error or a warning means someone has to act on it. If nobody can act on it, it is not an error or a warning.
* Every error in Sentry carries a `feature` tag that names its home ticket. [Error reporting](/engineering/development-process/how-to-decide-what-to-build/signals/error-reporting.md) says how that tag routes it and what the count under a home ticket means.
* We keep the number of errors and warnings within reasonable limits, during the rollout and after it. The [stability targets](/engineering/development-process/how-to-build/tickets/rollout.md#success) on the home ticket set those limits.
* When in doubt, the error goes to Sentry. From the errors that actually reach us, we decide which ones are worth handling in the product itself, for example by setting a bridge to degraded.
* Every error message follows Nielsen Norman Group's [error-message guidelines](#the-error-message).

### Feature tags

**Each tag value has exactly one home ticket, either a rollout ticket or a** [**monitoring ticket**](/engineering/development-process/how-to-build/tickets/monitoring.md)**.** The tag is that feature's [public name](/engineering/development-process/how-to-build/tickets.md#public-names). That ticket's owner acts on the errors with that tag. Without a home ticket, nobody feels responsible for a new Sentry issue.

**Today the tag is set in several ways, and ideally there would be one.** In umh-core, FSMv2 code names a feature when it reports an error. Errors inside a worker get the worker's type, such as `historian-timescale`. In the Management Console, the error telemetry list sets paths such as `instances::cpu-health::payload-rejected`. Some frontend code sets free text such as `historian`.

So one feature can have several tag values. The CPU status, for example, reports under `cpu`, `support_cpu` and `instances::cpu-health::payload-rejected`. Until there is one scheme, the home ticket lists all of its values.

**Many errors still have no feature tag.** They come from umh-core code older than FSMv2 and from older error helpers in the Management Console. benthos-umh does not report to Sentry at all.

### Transient and persistent errors

**An error is transient, persistent transient or persistent.**

* A transient error, such as a network hiccup, goes away after a few retries.
* A persistent transient error, such as a network that keeps failing, goes away only after a long time or after someone fixes the cause.
* A persistent error, such as a poisoned message or a server that rejects the credentials, never goes away, no matter how often it is retried.

### Questions for every error

**Whenever an error can appear in your code, you answer these questions while you build it.**

1. **Can a retry fix it?** Then it is a transient error. We retry it without showing it to the user. If the retries keep failing, it becomes a persistent transient error. A persistent error is never retried.
2. **Can the person running the system fix the cause?** Then the product shows the error to them, for example by setting the [bridge](https://docs.umh.app/usage/data-flows/bridges) to [degraded](/engineering/development-process/how-to-build/coding-standards/architecture/fsmv2-workers.md). Say the customer's network connection to a machine drops. Only the customer can fix that network. So the bridge goes to degraded and says why. The [user](/product/who-we-build-for.md#our-users) should never feel the need to open the logs in umh-core, because those logs are for developers.
3. **Can only UMH fix the cause, for example a bug in our code?** Then it goes to [Sentry](https://sentry.io), with all the information someone needs to debug it later. Sentry is our main source for troubleshooting, because we have no easy access to the logs at a customer. The error also goes to the logs. They help when a user and a developer look at a problem together, or when we reproduce it internally. There are no error or warning logs without Sentry.
4. **What happens to the data that failed?** This applies inside the data infrastructure. [Retries and dead-letter queues](/engineering/development-process/how-to-build/coding-standards/architecture/data-integrity/retries-and-dead-letter-queues.md) in Data integrity answers it.

Questions 1 to 3 apply everywhere, including the [Management Console](https://docs.umh.app/management-console) and its communication with [umh-core](https://docs.umh.app/).

**An error in Sentry that UMH doesn't need to fix is a defect in the source.** The owner of its home ticket fixes the code. The questions above say how: the error is retried, only shown to the user, or not reported as an error at all. Ignoring it in Sentry alone isn't enough.

### The error message

**The error message is written for the person running the system.**

It uses the product's names and says whether that person has to act. It never blames the user. A bridge that cannot reach a PLC, for example, says "The device at 192.168.1.100 isn't responding. Check if it's powered on and connected to the network."

These are the [error-message guidelines](https://www.nngroup.com/articles/error-message-guidelines/) from Nielsen Norman Group. Their article explains each one with an example.

* Visibility
  * Display the error message close to the error's source.
  * Use noticeable, redundant, and accessible indicators.
  * Design errors based on their impact.
  * Avoid prematurely displaying errors.
* Communication
  * Use human-readable language.
  * Concisely and precisely describe the issue.
  * Offer constructive advice.
  * Take a positive tone and don't blame the user.
* Efficiency
  * Safeguard against likely mistakes.
  * Preserve the user's input.
  * Reduce error-correction effort.
  * Concisely educate on how the system works.
* Mitigate total failure with novelty.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://engineering.umh.app/engineering/development-process/how-to-build/coding-standards/architecture/error-management.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
