# Fehlersuche

Wenn etwas nicht ankommt: die häufigsten Ursachen und wo du nachsiehst.

Wenn etwas nicht ankommt, liegt es fast immer an einer von wenigen Ursachen. Such unten die Überschrift, die zu dem passt, was du siehst.

## Zuerst: das Protokoll

Jedes Packlet hat ein Protokoll. Tippe im Kanal oben auf Avatar oder Namen und dann auf **Protokoll**. Dort stehen die letzten 50 Aufrufe mit Status:

- Aufrufe deines Tools, die angekommen sind: erfolgreiche und solche mit `400`.
- Jeder Versuch von Samy, deinen Webhook zu erreichen, mit dem Status deiner Antwort.

> **Hinweis:** Aufrufe mit `401`, `409` und `429` stehen nicht im Protokoll. Ist der Schlüssel falsch, weiß Samy nicht, zu welchem Packlet der Aufruf gehört. Bleibt das Protokoll leer, sieh dir also die Antwort an, die dein Tool bekommen hat.

## Der Aufruf schlägt fehl

Die Antwort sagt, warum. Lass dein Tool Status und Body ausgeben:

| Du bekommst | Ursache | Lösung |
|---|---|---|
| `401` `missing_key` | Der Header fehlt. | `Authorization: Bearer <Schlüssel>` setzen. Auf das Wort `Bearer` und das Leerzeichen achten. |
| `401` `invalid_key` | Der Schlüssel stimmt nicht. | Ist die Umgebungsvariable gesetzt und vollständig (`samy_` und 32 Zeichen)? Wurde in der App ein neuer Schlüssel erzeugt? Dann gilt nur noch der neue. |
| `400` `invalid_body` | Ein Feld passt nicht. | `details` nennt das Feld. Häufig: `text` fehlt oder ist leer, ein Text ist zu lang, eine `id` kommt doppelt vor. |
| `400` ohne `error` von Samy | Der Body ist kein gültiges JSON. | Anführungszeichen und Kommas prüfen. In der Shell den Body in einfache Anführungszeichen setzen. |
| `409` `wrong_kind` | `PUT /v1/ui` bei einem Kanal. | Ein Packlet mit **Eigene App bauen** verbinden. |
| `429` `rate_limited` | Mehr als 60 Aufrufe pro Minute. | Warten, wie `retry-after` sagt. Schickt eine Schleife zu oft? |
| keine Antwort | Dein Tool erreicht Samy nicht. | Adresse prüfen: `https://api.packlets.app`. Hat der Rechner Internet? |

Alle Kennungen stehen unter [Fehlercodes](https://packlets.app/docs/fehler.md).

## Die Nachricht ist da, aber kein Push

Der Aufruf antwortet mit `200`, die Nachricht steht im Kanal, nur auf dem Sperrbildschirm erscheint nichts. Dann wurde der Push absichtlich nicht geschickt, oder das Handy zeigt ihn nicht:

1. **Ist Push für das Packlet an?** In den Einstellungen des Packlets: Push an, Kanal nicht stumm.
2. **Ist gerade Ruhezeit?** Dann kommt nur `priority: "high"` durch.
3. **Sind Mitteilungen für Samy erlaubt?** In den Einstellungen des Handys unter Mitteilungen.
4. **Ist ein Fokus oder „Nicht stören“ aktiv?** Das Handy hält Pushes dann zurück.
5. **Ist die App gerade offen?** Dann erscheint die Nachricht direkt im Kanal.

Ein ausgefallener Push wird nicht nachgeholt. Mehr dazu unter [Push, Ton und Ruhezeit](https://packlets.app/docs/push.md).

## Der Webhook kommt nicht an

Du tippst einen Knopf oder bedienst ein Element, aber dein Tool merkt nichts. Sieh ins Protokoll:

| Im Protokoll | Ursache | Lösung |
|---|---|---|
| kein Webhook-Eintrag | Das Packlet hat keine Webhook-URL, oder der Knopf hat eine `url` und ist damit ein Link-Knopf. | Webhook-URL in den Einstellungen eintragen. Beim Knopf `url` weglassen. |
| Status `0` | Samy erreicht die Adresse nicht: falsche Adresse, Server aus, Tunnel beendet, Antwort später als 10 Sekunden, oder die Adresse ist privat. | Adresse im Browser oder mit `curl` von außen prüfen. Schneller antworten. |
| Status `401` oder `403` | Dein Tool lehnt ab, meist wegen der Signatur. | Siehe nächster Abschnitt. |
| Status `404` oder `405` | Der Pfad stimmt nicht, oder dein Empfänger nimmt kein `POST` an. | Adresse mit dem Pfad deines Empfängers vergleichen, zum Beispiel `/samy`. |
| Status `301`, `302`, `308` | Deine Adresse leitet weiter. Samy folgt Weiterleitungen nicht. | Die endgültige Adresse eintragen, oft mit `https://` oder mit `www`. |
| Status `500` | Dein Tool ist beim Verarbeiten abgestürzt. | Ins Log deines Tools sehen. Samy versucht es noch mehrmals. |
| Status `200` oder `204` | Der Webhook ist angekommen. | Der Fehler liegt danach, in deiner Logik. Gib das Ereignis aus. |

Lässt sich die Adresse gar nicht erst eintragen, ist sie nicht erlaubt: Sie muss mit `https://` beginnen, öffentlich erreichbar sein und darf keine Zugangsdaten enthalten.

Ereignisse aus der Zeit, in der der Webhook nicht erreichbar war, kommen nicht nachträglich. Nur die letzten Versuche, etwa zehn Minuten lang.

## Die Signatur stimmt nicht

Dein Empfänger bekommt die Anfrage, aber die Prüfung schlägt fehl. Die üblichen Gründe:

- **Der Body wurde verändert.** Rechne über die rohen Bytes, nicht über das JSON, das dein Framework daraus gemacht hat. In Flask ist das `request.get_data()`, in Express brauchst du `express.raw()` statt `express.json()`.
- **Das Geheimnis ist falsch gebildet.** Es ist der SHA-256-Hash des Schlüssels als Hex-Text, und dieser Text ist der HMAC-Schlüssel. Nicht der Schlüssel selbst und nicht die rohen Hash-Bytes.
- **Der Schlüssel ist alt.** Nach „Neuen Schlüssel erzeugen“ gilt auch für die Signatur der neue.
- **Das `sha256=` fehlt** im Vergleich. Der Header beginnt damit.

Der fertige Code steht unter [Webhook einrichten](https://packlets.app/docs/webhook.md#4-signatur-pruefen).

## Die App zeigt nicht, was ich erwarte

| Was du siehst | Ursache |
|---|---|
| Die App wartet weiter auf „Verbunden“. | Sie wartet auf den ersten erfolgreichen `POST /v1/push`, bei einer App auf den ersten `PUT /v1/ui`. |
| Ein Element ist breiter oder höher als angegeben. | Mindestgrößen, oder die App hat Platz für die Beschriftung geschaffen. Siehe [Layout](https://packlets.app/docs/layout.md). |
| Formatierung erscheint als Zeichen. | Nur Überschriften, Listen und Fettdruck werden umgewandelt. Siehe [Formatierung](https://packlets.app/docs/senden.md#formatierung). |
| Das Bild fehlt. | `image` muss eine öffentliche `http(s)`-Adresse sein, die das Handy direkt laden kann. |
| Ein Aktions-Knopf lässt sich nicht noch einmal tippen. | So ist es gedacht: einmal pro Nachricht. Für mehrfaches Tippen einen [Button als Element](https://packlets.app/docs/nachrichten-elemente.md) nehmen. |
| Die Seite einer App bleibt leer. | Nur `https://`. Im Browser öffnen und prüfen, ob sie dort lädt. |

## Immer noch unklar

Schick den Aufruf einmal von Hand mit `curl -i`. So siehst du Status, Header und Body der Antwort, ohne dass dein eigener Code dazwischen steht:

```bash
curl -i https://api.packlets.app/v1/push \
  -H "Authorization: Bearer $SAMY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Test"}'
```
