Webhook-Fehlerbehebung
Behebe ein fehlgeschlagenes Testereignis oder eine fehlgeschlagene Zustellung nach Symptom, mit den exakten Meldungen, die GrowWriter zeigt, was jede bedeutet und was du tun kannst.
Zuletzt aktualisiert am
Jeder Eintrag unten beginnt mit dem, was du siehst, sagt in einfachen Worten, was es bedeutet, und endet mit der Lösung. Fang beim ersten Eintrag an: Fast jedes Problem bei der ersten Verbindung löst sich, sobald du den echten Statuscode findest.
Finde zuerst den echten Statuscode
Was du tust. Schicke von deinem eigenen Rechner aus eine unsignierte
Testanfrage an deinen Endpoint und schau nur auf die Statuszeile und den
Header Location:
curl -sS -o /dev/null -D - -X POST \
-H "Content-Type: application/json" -d '{}' \
https://your-site.com/webhooks/growwriter | grep -iE "^(HTTP|Location)"So liest du das Ergebnis. Die Anfrage ist nicht signiert, ein 401 ist
also die gute Antwort: Dein Endpoint läuft und lehnt unsignierte Anfragen
ab, genau wie er soll.
| Du bekommst | Es bedeutet |
|---|---|
HTTP … 401 oder 400 | Gut. Der Endpoint läuft und prüft Signaturen. Signierte Anfragen werden funktionieren. |
HTTP … 3xx + Location: | Deine URL leitet weiter. Nutze stattdessen die Adresse aus Location:. Siehe Weiterleitungen. |
HTTP … 404 | Falscher Pfad, oder die Route ist nicht deployt. |
HTTP … 405 | Die Route existiert, akzeptiert aber kein POST. |
HTTP … 500 | Dein Code ist abgestürzt. Meist fehlt eine Umgebungsvariable (der Schlüssel). |
| Verbindungsfehler / Timeout | DNS, Firewall, oder die Website ist nicht öffentlich. |
Bekommst du ein 3xx, führe den Befehl mit der Adresse aus Location:
erneut aus, bis du ein 4xx bekommst. Diese letzte Adresse ist die, die du
in GrowWriter einträgst.
Das Testereignis schlägt mit HTTP 301, 302, 303, 307 oder 308 fehl
Was du siehst. Der Dialog zeigt Deine Endpoint-URL leitet weiter. Gib die Adresse ein, zu der sie weiterleitet, und versuche es erneut, mit dem Weiterleitungsziel in der Zeile darunter.
Was es bedeutet. Deine Website hat geantwortet: „Geh stattdessen dorthin". Browser folgen dem stillschweigend, deine Website sieht also gut aus, wenn du sie öffnest. GrowWriter folgt nie einer Weiterleitung: Ihr zu folgen könnte den Anfrage-Body verlieren oder die Signatur kaputt machen. Eine Weiterleitung zählt also immer als fehlgeschlagene Zustellung, und alle drei Versuche gehen an exakt die URL, die du eingegeben hast.
Die üblichen Ursachen:
| Ursache | Typische Weiterleitung |
|---|---|
example.com gegen www.example.com | Dein Host leitet das eine auf das andere um. Nutze das, auf das er umleitet. |
http:// statt https:// | http://… → https://… |
| Ein abschließender Schrägstrich, den dein Framework ergänzt oder entfernt | /webhook → /webhook/ oder umgekehrt |
| Ein Sprachpräfix, das dein Framework ergänzt | /api/webhook → /en/api/webhook |
| Eine Preview-URL, die neu vergeben wurde | *.vercel.app → deine Produktionsdomain |
| Eine CDN- oder Proxy-Regel („Always use HTTPS", Page Rules) | jede der obigen |
Lösung. Kopiere die Adresse aus der Fehlermeldung (oder aus dem Header
Location: in der Prüfung oben) und trage sie als
Endpoint-URL ein. Ist der Verbindungsdialog noch offen, klicke auf
Zurück; hast du ihn schon geschlossen, klicke auf URL bearbeiten in
der Webhook-Zeile der Seite Kanäle. Beides behält deinen
Signaturschlüssel. Trennen und neu verbinden erzeugt stattdessen einen neuen
Schlüssel, den du auf deinem Server aktualisieren müsstest.
„Dein Endpoint hat nicht rechtzeitig geantwortet"
Was es bedeutet. GrowWriter hat 10 Sekunden auf eine Antwort gewartet und aufgegeben. Jeder der drei Versuche bekommt seine eigenen 10 Sekunden.
Lösung. Antworte, bevor du langsame Arbeit machst. Die Anleitung
beschreibt zwei sichere Muster: Halte den Handler so, dass er gefahrlos
zweimal laufen kann, und lass eine Wiederholung die Arbeit zu Ende bringen,
oder antworte zuerst mit 200 und
erledige die schwere Arbeit in einem Hintergrund-Job. Siehe
Was ist mit dem 10-Sekunden-Limit?.
„Dein Endpoint hat die Zustellung abgelehnt"
Was es bedeutet. Dein Endpoint hat mit einem Status geantwortet, der
kein 2xx ist. Die Meldung zitiert diesen Status und die ersten 200 Zeichen
deines Antwort-Bodys. Gib aus deinem Handler also einen kurzen Grund als
reinen Text zurück, und du liest ihn direkt im Dialog. Der Status sagt dir,
wo du suchen musst:
401oder403: Deine Signaturprüfung hat Nein gesagt. Siehe Die Signatur stimmt nie überein.404: Falscher Pfad. Vergleiche die URL in GrowWriter mit deiner Route.405: Die Route akzeptiert keinPOST.413: Dein Server lehnt Bodys dieser Größe ab. Ein voller Artikel kann mehrere hundert Kilobyte haben. Siehe große Payloads.500: Dein Code ist abgestürzt. Prüfe deine Server-Logs; eine fehlende Umgebungsvariable für den Schlüssel ist die häufigste Ursache.
„Beitrag ansehen" fehlt oder öffnet die falsche Seite
Was es bedeutet. Der Link ist genau die URL, die dein Endpoint im Body
seiner 2xx-Antwort zurückgegeben hat, als {"url": "https://…"}.
Antwortest du mit irgendetwas anderem, gibt es keinen Link. GrowWriter hat
keinen anderen Weg zu erfahren, wo deine Website den Beitrag abgelegt hat.
Lösung. Gib die öffentliche URL des Beitrags aus deinem Handler zurück,
sobald der Beitrag gespeichert ist. Sie muss eine absolute http- oder
https-URL sein; relative Pfade und andere Schemata werden ignoriert. Die
Regeln stehen unter
Die Antwort. Zwei Dinge solltest
du wissen:
- Antwortest du mit
200, bevor du den Beitrag anlegst (das Hintergrund-Job-Muster), kennst du seine URL noch nicht, der Dialog zeigt also keinen Link. - Der gespeicherte Link wird bei jeder erfolgreichen Lieferung ersetzt. Zeigt ein Link auf eine alte Adresse, veröffentliche den Artikel erneut, und die aktuelle Antwort deines Endpoints ersetzt ihn.
„Zustellung nach mehreren Versuchen fehlgeschlagen"
Was es bedeutet. GrowWriter konnte in drei Versuchen gar keine Verbindung zu deinem Endpoint aufbauen: DNS ist fehlgeschlagen, die Verbindung wurde abgelehnt, oder die Website ist aus dem Internet nicht erreichbar.
Lösung. Prüfe, ob die URL erreichbar ist, https:// verwendet und
öffentlich ist. Adressen in privaten Netzen und localhost sind aus
Sicherheitsgründen gesperrt. Um echte Ereignisse während der Entwicklung auf
deinem Rechner zu empfangen, nutze einen Tunnel-Dienst (ngrok, cloudflared)
und trage die HTTPS-Adresse des Tunnels ein.
Die URL wird beim Verbinden abgelehnt
GrowWriter prüft die URL, bevor es sie speichert. Die drei Meldungen und ihre Bedeutung:
- Die Webhook-URL muss HTTPS verwenden: Nur
https://wird akzeptiert. - Die Webhook-URL zeigt auf eine private Adresse und kann nicht verwendet
werden: Der Hostname löst auf eine lokale oder private Netzwerkadresse
auf (
localhost,10.x,192.168.xund ähnliche). Nutze eine öffentliche Adresse oder einen Tunnel. - Die Webhook-URL ist ungültig: Die URL lässt sich nicht parsen, enthält einen Benutzernamen oder ein Passwort, oder ihr Hostname lässt sich nicht auflösen.
GrowWriter testet an dieser Stelle nicht, ob der Endpoint antwortet. Dafür ist Testereignis senden da.
Die Signatur stimmt nie überein
Arbeite diese Liste der Reihe nach ab. Jeder Punkt erklärt eine ganze Klasse von Fehlern:
- Prüfe über den rohen Body. Berechne die Signatur über exakt die Bytes, die du empfangen hast, vor jedem JSON-Parsing. Parsen und neu serialisieren ändert die Bytes.
- Nutze den ganzen Schlüssel. Der Schlüssel ist der komplette String,
whsec_-Präfix inklusive. - Prüfe die Umgebungsvariable. Gleicher Name in deinem Code und bei deinem Host, gesetzt für die Umgebung, die den Endpoint ausliefert, und nach dem Setzen neu deployt.
- Prüfe das Fünf-Minuten-Fenster. Geht die Uhr deines Servers um mehr als fünf Minuten falsch, sieht jede Signatur abgelaufen aus. Synchronisiere die Uhr.
- Vergleiche das Header-Format.
X-GrowWriter-Signatureistt=<Unix-Sekunden>,v1=<64 Hex-Zeichen>, und der signierte String ist"<t>.<roher Body>".
Der lokale Test signiert eine Anfrage genau so wie GrowWriter, du kannst deine Prüfung also bestätigen, ohne auf eine echte Lieferung zu warten.
Der Test klappt, aber echte Artikel schlagen fehl
Was es bedeutet. Der ping ist winzig. Ein echter Artikel trägt seinen
Inhalt dreimal (Markdown, HTML und Blöcke) und hat üblicherweise ein paar
hundert Kilobyte; lange Artikel können 1 MB überschreiten. Server und
Frameworks begrenzen JSON-Bodys oft deutlich darunter.
Lösung. Erhöhe das Body-Limit auf der Route (zum Beispiel
express.raw({ type: 'application/json', limit: '10mb' }); der Standard von
Express liegt bei 100 KB), und stelle sicher, dass deine Speicherlogik den
vollen Payload verarbeitet, nicht nur die Felder, die der Test genutzt hat.
Der Test klappt, aber der erste Artikel schlägt auf Vercel oder Netlify mit einem 500 fehl
Was es bedeutet. Dein Handler schreibt eine Datei neben deinen Code.
Serverless-Hosts mounten dieses Verzeichnis schreibgeschützt, der
Schreibvorgang wirft also einen Fehler (EROFS) und der Endpoint antwortet
mit 500. Der Test klappt, weil der Ping zurückkehrt, bevor irgendetwas
gespeichert wird.
Lösung. Speichere den Artikel in einer Datenbank, über eine CMS-API oder
in einem Objektspeicher statt in einer lokalen Datei. Die Beispiele für
Next.js und Express in der Anleitung loggen den Beitrag genau aus diesem
Grund; ersetze die Log-Zeile durch deinen Speicheraufruf. Brauchst du nur
eine temporäre Datei, ist /tmp beschreibbar, wird aber zwischen Aufrufen
geleert.
Ich habe meinen Signaturschlüssel verloren
Was es bedeutet. Der Schlüssel wird einmal angezeigt, im Verbindungsdialog, und verschlüsselt gespeichert. GrowWriter kann ihn nicht erneut anzeigen.
Lösung. Trenne den Webhook auf der Seite Kanäle und verbinde ihn neu. Das erzeugt einen neuen Schlüssel und zieht den alten zurück: Aktualisiere die Umgebungsvariable auf deinem Server, deploye neu und sende dann ein Testereignis.
Der Artikel ist live auf meiner Website, aber meine CMS-Verwaltung zeigt einen Validierungsfehler
Was du siehst. Etwas wie Key on object value "growwriterId" is not allowed, oder ein abgelehnter Datumswert.
Was es bedeutet. Dein Endpoint hat ein Feld gespeichert, das dein CMS nicht deklariert (meist die GrowWriter-id), oder einen Wert in einem Format, das das Feld nicht akzeptiert (meist einen vollen Zeitstempel in einem reinen Datumsfeld).
Lösung. Lege in deinem Inhaltsmodell ein eigenes Feld für die id an, und wandle Datumswerte in das Format um, das dein CMS erwartet. Beides wird in Speichere den Artikel in deinem CMS erklärt.
Ein Beitrag ist stillschweigend wieder ein Entwurf geworden
Was es bedeutet. Der Payload hat kein Veröffentlicht-Flag. Behandelt dein CMS ein fehlendes Entwurfsfeld als „Entwurf", ist der Beitrag nur so lange veröffentlicht, bis ihn jemand in der Verwaltung speichert.
Lösung. Setze den Veröffentlichungsstatus selbst, explizit, wenn du
article.published und article.updated verarbeitest. Siehe
Regel 3.
Mein Build scheitert an { oder < im Artikel
Was es bedeutet. Artikeltext enthält normale Zeichen wie {, } und
<. Kompilierst du das Markdown über MDX, JSX oder eine Template-Engine,
werden diese Zeichen als Code gelesen.
Lösung. Speichere das Markdown als Daten und rendere es mit einem
Markdown-Renderer, oder escape diese Zeichen vor dem Kompilieren.
content.html ist bereits escaped und kann direkt eingefügt werden. Siehe
Regel 6.
Bilder sind riesig, fehlen, oder ihre URLs haben sich geändert
- Riesig: Bilder kommen in Originalauflösung an und können 10 MB überschreiten. Verkleinere und komprimiere sie beim Herunterladen.
- Fehlen:
coverImagefehlt, wenn der Artikel kein Titelbild hat;imagesist ein leeres Array, wenn es keine Inline-Bilder gibt. Prüfe, ob der Schlüssel da ist, bevor du ihn liest. - URLs geändert: Ein Bild, das im Artikel ersetzt wurde, bekommt bei der nächsten Lieferung eine neue URL. Unveränderte Bilder behalten ihre URLs.
Alle drei Fälle behandelt Regel 5.
Ich habe denselben Artikel zweimal erhalten
- Gleiche Liefer-Id: eine Wiederholung. Dein Endpoint hat beim ersten Versuch zu spät oder mit einem Fehler geantwortet. Überspringe Arbeit, die du für diese Id schon erledigt hast.
- Andere Liefer-Id, wieder
article.published: Der Artikel wurde an eine zweite Webhook-Verbindung veröffentlicht, oder die erste Verbindung hatte noch keine erfolgreiche Lieferung. Upserte überarticle.id, dann überschreibt die zweite Kopie die erste.
Ich habe einen Artikel in GrowWriter gelöscht, aber er ist noch auf meiner Website
Was es bedeutet. Einen Artikel zu löschen (oder den Webhook zu trennen)
sendet article.unpublished mit id, slug und language des Artikels,
und sonst nichts. Behandelt dein Handler jedes Ereignis außer dem Ping als
Artikel zum Speichern, hat er das Ereignis entweder ignoriert oder versucht,
einen Artikel ohne Inhalt zu speichern, und mit 500 geantwortet.
Lösung. Verarbeite article.unpublished vor dem Speichern: Suche den
Beitrag über article.id und verstecke oder lösche ihn, je nachdem, was
deine Website bevorzugt. Jedes Empfänger-Beispiel in der Anleitung hat diesen
Zweig. Das Ereignis folgt den normalen Zustellregeln (drei Versuche, dann
nichts mehr). War dein Endpoint zu dem Zeitpunkt also nicht erreichbar,
bleibt der Beitrag stehen; GrowWriter wiederholt es später nicht.
Der Slug enthält nicht-lateinische Zeichen oder hat sich mit dem Titel nicht geändert
Der Slug wird einmal aus dem Titel abgeleitet, wenn der Brief erzeugt wird.
Lateinische Akzente werden aufgelöst (qué → que), aber Buchstaben aus
anderen Schriften bleiben erhalten, ein japanischer Titel erzeugt also einen
japanischen Slug: percent-encode ihn, bevor du ihn in eine URL setzt. Er ist
nie leer. Den Titel im Editor zu bearbeiten behält den Slug, die Adresse des
Beitrags bleibt also stabil; nur einen neuen Titel im Writer zu wählen
erzeugt einen neuen Slug. Nutze den Slug nie als Dateinamen oder
Schlüssel; nimm article.id und behandle den Slug als Anzeigedaten.
„Zu viele Anfragen. Bitte versuche es später erneut"
Was es bedeutet. Dein Konto hat ein Limit erreicht: 20 Veröffentlichungsanfragen pro Stunde oder 60 Testereignisse pro Stunde. Nichts geht verloren. Der Artikel bleibt in deiner Bibliothek, und die Verbindung bleibt, wie sie war.
Lösung. Warte ein paar Minuten, dann veröffentliche erneut oder sende das Testereignis noch einmal. Veröffentlichst du an mehrere Kanäle auf einmal, zählt jeder Kanal als eine Anfrage.
Die Webhook-Zeile zeigt „Nicht bestätigt"
Was es bedeutet. Der Endpoint hat noch nie auf ein Testereignis oder eine Veröffentlichung geantwortet. GrowWriter prüft die Adresse beim Verbinden, ruft sie aber erst auf, wenn du es tust.
Lösung. Klicke auf Testereignis senden in der Webhook-Zeile. Gelingt es, wechselt die Zeile auf Verbunden. Schlägt es fehl, beginne mit der Statusprüfung, dann Weiterleitungen oder abgelehnt. An einen Webhook mit „Nicht bestätigt" zu veröffentlichen ist erlaubt, und die erste erfolgreiche Lieferung bestätigt ihn ebenfalls.
Kommst du nicht weiter?
Schreib uns aus der App heraus und schicke mit: die Liefer-Id (aus dem Header
X-GrowWriter-Delivery oder der Fehlermeldung), die Uhrzeit des Versuchs,
den Status, den dein Server zurückgegeben hat, und die Ausgabe von
der Statusprüfung. Mit diesen vier Dingen können wir
meist in einer Antwort helfen.