# Error Handling

Gutes Error Handling beginnt idealerweise damit, Fehler gar nicht erst entstehen
zu lassen. Klare UI Strukturen, verständliche Beschriftungen und sinnvolle
Defaults helfen dabei, Fehlbedienungen zu vermeiden. Da sich Fehler jedoch nie
vollständig verhindern lassen, ist ein solides Error Handling entscheidend.

---

# Best Practices

- **Fehlervermeidung:** Gestalte Oberflächen so, dass Fehler möglichst gar nicht
  erst entstehen.
- **Einfach formulieren:** Verwende klare, alltagstaugliche Sprache ohne
  Fachbegriffe (siehe
  [Fehlermeldung](/02-foundations/03-content-guidelines/03-fehlermeldungen)).
- **Handlung ermöglichen:** Zeige dem User, wie er den Fehler beheben oder
  weitermachen kann.

---

# Fehler beim Laden von Inhalten

Beim Laden von Inhalten können Fehler auftreten, zum Beispiel wenn ein Service
nicht erreichbar ist, ein Timeout entsteht oder ein technischer Fehler vorliegt.
In diesen Fällen sollte der Ladezustand beendet werden, damit User sehen, dass
ein Fehler eingetreten ist und sie nicht weiter warten müssen.

Die Fehlermeldung sollte immer dort erscheinen, wo der erwartete Inhalt wäre.
Für größere Bereiche wie
[LayoutCards](/04-components/structure/layout-card/overview) oder
[Sections](/04-components/structure/section/overview) eignet sich eine
[IllustratedMessage](/04-components/content/illustrated-message/overview) mit
dem Status Danger. Sie signalisiert deutlich, dass der Inhalt aktuell nicht
verfügbar ist, und bietet idealerweise eine Handlung an, zum Beispiel einen
[Button](/04-components/actions/button/overview) mit der Beschriftung "Erneut
laden".

```tsx
import {
  Flex,
  Heading,
  IconDanger,
  IllustratedMessage,
  LayoutCard,
  Text,
} from "@mittwald/flow-react-components";

export default () => {
  return (
    <Flex direction="column" gap="m">
      <Heading level={1} color="dark">
        Mein Projekt
      </Heading>

      <LayoutCard>
        <IllustratedMessage color="danger">
          <IconDanger />
          <Heading>Fehler beim Laden von Daten</Heading>
          <Text>
            Dieser Bereich konnte nicht geladen werden. Wir
            arbeiten daran das Problem zu beheben. Bitte
            habe etwas Geduld und probiere es später noch
            einmal.
          </Text>
        </IllustratedMessage>
      </LayoutCard>
    </Flex>
  );
}
```

Für kleinere, abgegrenzte UI Elemente wie Tabellen- oder Listenzeilen sollte ein
[AlertText](/04-components/status/alertText/overview) verwendet werden. So
bleibt der Kontext erhalten und der Fehler wirkt sich nicht auf die ganze
[Table](/04-components/structure/table/overview) oder
[List](/04-components/structure/list/overview) aus.

```tsx
import {
  AlertText,
  Avatar,
  Content,
  Flex,
  Heading,
  IconDomain,
  LayoutCard,
  ListItemView,
  Text,
  typedList,
} from "@mittwald/flow-react-components";

export default () => {
  const DomainList = typedList<{
    id: string;
    domain: string;

    target?: string;
  }>();

  return (
    <Flex direction="column" gap="m">
      <Heading level={1} color="dark">
        Domains
      </Heading>
      <LayoutCard>
        <DomainList.List
          aria-label="Domains"
          getItemId={(domain) => domain.id}
          loadingItemsCount={3}
        >
          <DomainList.StaticData
            data={[
              {
                id: "1",
                domain: "mjaofd6.project.space",
              },
              {
                id: "2",
                domain: "formel1.de",
                target: "Mein WordPress",
              },
              {
                id: "3",
                domain: "schumi-fanclub.de",
                target: "/home/xyz/ordner/tollerpfad",
              },
            ]}
          />
          <DomainList.Search />
          <DomainList.Item
            textValue={(domain) => domain.domain}
          >
            {(domain) => (
              <ListItemView>
                <Avatar>
                  <IconDomain />
                </Avatar>
                <Heading>{domain.domain}</Heading>
                <Text>
                  {domain.target ? (
                    domain.target
                  ) : (
                    <AlertText status="danger">
                      Fehler beim Laden
                    </AlertText>
                  )}
                </Text>

                <Content>
                  <small></small>
                </Content>
              </ListItemView>
            )}
          </DomainList.Item>
        </DomainList.List>
      </LayoutCard>
    </Flex>
  );
}
```

Um Errors auf kleine Bereiche zu begrenzen, nutzen wir im mStudio Loading und
Error Boundaries. Diese kapseln technische Fehler ab und sorgen für konsistentes
Feedback. Details dazu sind in der Guideline zu
[Boundaries (Internal)](/02-foundations/04-internal/01-boundaries) beschrieben.

---

# Fehler beim Durchführen von Aktionen

## Fehler durch ungültige Eingaben

Ungültige Eingaben treten häufig in Forms auf, zum Beispiel bei fehlenden
Pflichtfeldern oder falsch formatierten Werten. In diesen Fällen sollte das
Feedback direkt am Form Control erfolgen. User müssen sofort erkennen können,
was angepasst werden muss, ohne die Seite oder den Kontext zu verlassen. Weitere
Details dazu sind unter
[Forms (Validation)](/03-patterns/01-patterns/forms#validation) beschrieben.

## Fehler bei serverseitigen Aktionen

Aktionen, die einen Request an das Backend senden, können aus unterschiedlichen
Gründen fehlschlagen. Dazu zählen technische Fehler im System, Probleme bei der
Kommunikation mit dem Backend oder fehlende Berechtigungen.

Wenn eine Aktion fehlschlägt, sollte dies deutlich kommuniziert werden. Dafür
eignet sich ein [Modal](/04-components/overlays/modal/overview) mit einer
[IllustratedMessage](/04-components/content/illustrated-message/overview) im
Status Danger. Diese informiert darüber, dass die Aktion nicht durchgeführt
werden konnte, und erklärt kurz den Grund, sofern dieser für den User relevant
ist. Zusätzlich sollte immer ein Ausweg angeboten werden, zum Beispiel die
Aktion erneut auszuführen.

```tsx
import {
  Action,
  ActionGroup,
  Button,
  Content,
  Flex,
  Heading,
  IconDanger,
  IconProject,
  IllustratedMessage,
  LayoutCard,
  Modal,
  Text,
  useModalController,
} from "@mittwald/flow-react-components";

export default () => {
  const controller = useModalController();

  return (
    <Flex direction="column" gap="m">
      <Heading level={1} color="dark">
        Projekte
      </Heading>

      <LayoutCard>
        <IllustratedMessage>
          <IconProject />
          <Heading>Erstes Projekt anlegen</Heading>
          <Text>
            Du hast noch keine Projekte angelegt! Lege ein
            Projekt an und schon kannst du mit dem
            Entwickeln loslegen.
          </Text>
          <Action
            onAction={() => {
              controller.open();
            }}
          >
            <Button color="accent">Projekt anlegen</Button>
          </Action>
        </IllustratedMessage>
        <Modal controller={controller}>
          <Content>
            <IllustratedMessage color="danger">
              <IconDanger />
              <Heading>
                Fehler beim Ausführen der Aktion
              </Heading>
              <Text>
                Die Aktion konnte nicht ausgeführt werden.
                Wir arbeiten daran das Problem zu beheben.
                Bitte habe etwas Geduld und probiere es
                später noch einmal.
              </Text>
            </IllustratedMessage>
          </Content>
          <ActionGroup>
            <Action closeModal>
              <Button
                slot="primary"
                variant="soft"
                color="secondary"
              >
                Schließen
              </Button>
            </Action>
          </ActionGroup>
        </Modal>
      </LayoutCard>
    </Flex>
  );
}
```

Für Aktionen, die über einen längeren Zeitraum laufen und zunächst erfolgreich
an das Backend übermittelt werden, aber erst später fehlschlagen, eignen sich
besser [Notifications](/04-components/status/notification/overview). Ein
typisches Beispiel ist das Registrieren einer Domain. Weitere Details dazu sind
im
[Informationskonzept](/02-foundations/03-content-guidelines/02-informationskonzept)
beschrieben.
