Zum Hauptinhalt springen

Fehler

Jeder Fehler der API ist ein Problem nach RFC 9457 mit Content-Type: application/problem+json; charset=utf-8. Dieses hier stammt von einem synchronen Rendering, dessen Vorlage sich nicht kompilieren lässt:

{
"type": "https://docs.formfeed.dev/errors/template-syntax",
"title": "Template syntax error",
"status": 422,
"detail": "unknown block tag: endfo",
"code": "template_syntax_error",
"location": { "line": 41, "column": 3 },
"render_id": "rnd_7da09ab6cd9946b798c187c2a9350852",
"request_id": "req_4b7c1e9a2f3d4c5b8a6e7f9012"
}

Felder​

Jedes Problem hat diese Felder:

FeldBedeutung
codeStabiler, maschinenlesbarer Fehlercode. Verzweigen Sie anhand dieses Felds, nicht anhand von title oder detail.
statusDer HTTP-Status, im Body wiederholt. Er folgt immer aus dem Code, wie die Tabelle unten zeigt.
titleKurzbeschreibung des Codes; für jedes Problem mit diesem Code gleich.
detailWas bei dieser Anfrage schiefgelaufen ist, für Menschen und Logs. Der Wortlaut kann sich ändern; werten Sie ihn nie maschinell aus.
typeEin Link auf die Seite zu diesem Code.
request_idDie ID dieser Anfrage, req_ gefolgt von 26 Hex-Ziffern. Derselbe Wert steht im Antwort-Header X-Request-Id. Senden Sie einen eigenen Header X-Request-Id (bis zu 255 Buchstaben, Ziffern, _, - und =), dann verwendet Formfeed diesen. Geben Sie sie an, wenn Sie den Support kontaktieren.

Viele Probleme ergänzen eigene Felder:

FeldWo
issuesinvalid_request, wenn Body oder Query nicht zum API-Vertrag passen: ein Eintrag pro Problem, mit path (dem Feld, etwa mode oder post.watermark.text; leer für den Body als Ganzes) und message.
errorsdata_validation_error und einvoice_data_invalid: jede Stelle, an der die Daten nicht passen, mit path, message und bei E-Rechnungen der rule.
locationBei den Problemen eines Renderings, das während der Ausführung fehlgeschlagen ist. Bei einem Vorlagenfehler: line und column in dem Teil, der fehlschlug (Body, Kopf- oder Fußzeile; das Problem sagt nicht, welcher). Bei einer Word- oder PowerPoint-Vorlage: part (etwa word/document.xml) und, soweit bekannt, paragraph. null, wenn der Fehler keine Stelle in der Vorlage hat.
fieldDas Feld der Anfrage, um das es geht, etwa output, validate_data, post.merge_after oder storage.key.
indexIn einem Batch das fehlgeschlagene Element (ab 0 gezählt). Bei einem PDF-Tool die Position der Quelle in sources.
render_idDie rnd_…-ID des Renderings, um das es geht: ein synchrones Rendering oder ein PDF-Tool, das nach seiner Aufzeichnung fehlgeschlagen ist und das dann das Render-Protokoll und GET /v1/renders/{id} zeigen, oder das Quell-Rendering, das ein PDF-Tool nicht verwenden konnte.
feature, plan, limitforbidden, wenn der Plan etwas nicht enthält: welche Funktion, der Plan und die Anzahl, die der Plan erlaubt.
einvoice, accessibilityDie Berichte des Validators zu einer E-Rechnung oder einer PDF/UA-1-Datei, die durchgefallen ist.

Manche Codes ergänzen weitere Felder, etwa page_count bei page_limit_exceeded oder period_end bei quota_exceeded; die Seite des jeweiligen Codes führt sie auf.

Fehlgeschlagene asynchrone Renderings​

Ein asynchrones Rendering, ein Batch-Element und ein synchrones Rendering, das im Hintergrund weiterlief (eine Antwort 202), schlagen erst später fehl, die Anfrage liefert also kein Problem zurück. Der Fehler bleibt stattdessen am Rendering:

  • GET /v1/renders/{id} und der Webhook render.failed tragen ihn in error, in kürzerer Form: code, message (was detail sagen würde) und die Felder des Codes, etwa line und column oder page_count. Die Berichte zu E-Rechnung und PDF/UA stehen in den eigenen Feldern einvoice und accessibility des Renderings.
  • GET /v1/renders/{id}/result beantwortet ein fehlgeschlagenes Rendering mit dem vollständigen Problem, wie es die synchrone Anfrage getan hätte, einschließlich render_id.

Ein fehlgeschlagenes Rendering, seine übrigen Felder weggelassen:

{
"id": "rnd_7da09ab6cd9946b798c187c2a9350852",
"status": "failed",
"error": {
"code": "page_limit_exceeded",
"message": "Document has 212 pages; the plan allows 200",
"page_count": 212
}
}

Ein Rendering, das dreimal auf Seiten von Formfeed fehlgeschlagen ist, hat "code": "worker_exhausted", die message des letzten Versuchs und attempts; siehe Wiederholen.

Fehler im Code behandeln​

Die SDKs machen aus jedem Problem eine Fehlerklasse. TypeScript:

import { Formfeed, FormfeedError } from '@formfeed/sdk';

const client = new Formfeed({ apiKey: process.env.FORMFEED_API_KEY! });

try {
await client.renders.create({ template: 'invoice', data });
} catch (e) {
if (!(e instanceof FormfeedError)) throw e;
switch (e.code) {
case 'template_syntax_error':
case 'template_runtime_error':
// ein Fehler in der Vorlage: die verantwortliche Person benachrichtigen, nicht wiederholen
console.error('template error', e.message, e.problem, e.requestId);
break;
case 'quota_exceeded':
// keine Live-Renderings mehr senden, bis die Periode neu beginnt oder der Plan wechselt
break;
default:
throw e;
}
}

Python:

import os
from formfeed import Formfeed, FormfeedError

client = Formfeed(os.environ["FORMFEED_API_KEY"])

try:
client.renders.create(template="invoice", data=data)
except FormfeedError as e:
if e.code in ("template_syntax_error", "template_runtime_error"):
# ein Fehler in der Vorlage: die verantwortliche Person benachrichtigen, nicht wiederholen
print("template error", e.message, e.problem, e.request_id)
elif e.code == "quota_exceeded":
pass # keine Live-Renderings mehr senden, bis die Periode neu beginnt oder der Plan wechselt
else:
raise
TypeScript (FormfeedError)Python (FormfeedError)Bedeutung
codecodeDer code des Problems oder ein eigener Code des SDK (siehe unten)
statusstatusDer HTTP-Status; 0, wenn keine Antwort ankam
messagemessageDas detail des Problems, sonst sein title
problemproblemDer ganze Body des Problems mit allen Feldern oben; null bzw. None bei einem Fehler des SDK
requestIdrequest_idDer Header X-Request-Id der Antwort

Codes, die die SDKs selbst auslösen, ohne Problem der API: network_error (keine Antwort nach den Wiederholungen, eine Zeitüberschreitung der Anfrage eingeschlossen), timeout (nur von waitFor bzw. wait_for, das das Warten auf ein Rendering oder einen Job aufgegeben hat), not_ready (Download eines Renderings ohne Datei), download_failed, invalid_response (TypeScript: eine Erfolgsantwort, die kein JSON ist) und http_<status> für eine Fehlerantwort ohne code.

renders.waitFor bzw. wait_for löst bei einem fehlgeschlagenen Rendering keinen Fehler aus: Es gibt das Rendering mit status: "failed" zurück, und sein error sagt, warum.

Wiederholen​

Die SDKs wiederholen 429, 503 und Netzwerkfehler selbst: bis zu 3-mal (maxRetries bzw. max_retries, 0 schaltet es ab), wobei sie die Sekunden aus Retry-After abwarten, wenn die Antwort den Header hat, sonst 0,5, 1 und 2 Sekunden, jeweils plus bis zu 0,25 Sekunden Zufall und nie mehr als 30 Sekunden am Stück. Eine Anfrage, die innerhalb der Zeitgrenze des Clients (timeoutMs bzw. timeout, standardmäßig 120 Sekunden) keine Antwort erhält, zählt als Netzwerkfehler. Jeder Aufruf, der ein Rendering erzeugt (Renderings, Batches, PDF-Tools), sendet einen erzeugten Idempotency-Key, und seine Wiederholungen verwenden ihn erneut. 500, 502 und 504 wiederholen die SDKs nie. Siehe die SDK-Seiten zu TypeScript und Python.

Ohne SDK, oder für das, was die SDKs Ihnen überlassen:

AntwortWiederholen?Wie
429 rate_limitedjaNach den Sekunden aus Retry-After, mit demselben Idempotency-Key.
503 region_unavailable, office_unavailable, conformance_unavailablejaNach den Sekunden aus Retry-After, mit demselben Idempotency-Key.
500 worker_exhausted, tool_failedja, einige MaleMit wachsenden Pausen (etwa 5, 30 und 120 Sekunden) und demselben Idempotency-Key. Scheitert es weiter, senden Sie die request_id an den Support.
500 pdfa_conversion_failedneinDasselbe Dokument scheitert auf dieselbe Weise; senden Sie die render_id an den Support.
504 render_timeoutnur, wenn die Ursache vorbei istEin langsamer Server für Bilder oder Schriften kann sich erholen; eine zu langsame Vorlage oder Seite scheitert wieder. Siehe die Seite des Codes.
Gar keine Antwort (Zeitüberschreitung, abgebrochene Verbindung)jaMit demselben Idempotency-Key: Ist der erste Versuch doch angekommen, erhalten Sie dessen Antwort statt eines zweiten Renderings.
Jede andere 4xx, und 501neinBeheben Sie, was das Problem nennt, und senden Sie die Anfrage dann mit einem neuen Idempotency-Key oder ohne.

Warum ein neuer Schlüssel nach einer 4xx: Die erste Antwort auf einen POST mit Idempotency-Key wird 24 Stunden pro Workspace gespeichert und bei jeder Wiederholung dieses Schlüssels erneut geliefert, mit Idempotent-Replayed: true. Das gilt auch für Probleme. Nur Antworten ab 500 werden nicht gespeichert, ebenso wenig eine 401 oder eine 429 des Rate-Limits, die beantwortet werden, bevor der Schlüssel betrachtet wird. Eine korrigierte Anfrage mit dem alten Schlüssel erhält also das alte Problem zurück.

Asynchrone Renderings und Batch-Elemente wiederholt die Warteschlange selbst, wenn sie auf Seiten von Formfeed fehlschlagen (ein Status ab 500, außer pdfa_conversion_failed): drei Versuche, der zweite 5 Sekunden und der dritte 10 Sekunden nach dem vorigen. Schlägt auch der dritte fehl, endet das Rendering mit worker_exhausted und behält die message des letzten Versuchs. Jeder andere Fehler beendet das Rendering sofort. Um ein fehlgeschlagenes asynchrones Rendering selbst erneut zu versuchen, senden Sie die Anfrage mit einem neuen Idempotency-Key: Der alte Schlüssel liefert die gespeicherte 202 des fehlgeschlagenen Renderings.

Ein fehlgeschlagenes Rendering kostet nichts, gleich mit welchem Code.

Alle Codes​

HTTPCodeBedeutungWiederholen
400invalid_requestBody oder ein Parameter passen nicht zum API-Vertrag, oder eine Kombination von Feldern ist nicht erlaubt.nein
401unauthorizedDie Anfrage enthält keinen API-Schlüssel, oder der Schlüssel ist unbekannt, widerrufen oder abgelaufen.nein
402quota_exceededDie Einheiten der aktuellen Periode sind aufgebraucht und der Plan erlaubt keinen Mehrverbrauch, oder der Mehrverbrauch hat seine Obergrenze erreicht.nein
403forbiddenDem Schlüssel fehlt der Scope, den dieser Endpunkt braucht, dem Plan fehlt die Funktion, oder der Aufrufer darf das nicht.nein
403test_output_unavailableEin Test-Rendering im Free-Plan hat eine Word- oder PowerPoint-Vorlage nach ihrem eigenen Format gefragt; es erzeugt nur das markierte PDF.nein
404not_foundDas Rendering, der Job, die Datei, der Webhook, das Partial oder der Pfad existiert in diesem Workspace nicht.nein
404template_not_foundKeine Vorlage mit diesem Slug oder dieser ID hat im Workspace des Schlüssels die Version, die die Anfrage nennt.nein
404channel_not_foundDie Anfrage nennt einen Release Channel, den die Vorlage nicht hat.nein
409conflictEin Slug ist vergeben, die Vorlage oder das geteilte Partial hat sich seit Ihrer Basisversion geändert, oder ein Gerätecode wurde schon verwendet.nein
409schema_breaking_changeVeröffentlichen oder Verschieben eines Channels würde eine Version live schalten, deren gespeichertes Datenschema Aufrufer der aktuellen bricht.nein
409channel_in_useRenderings der letzten Stunde haben den Channel verwendet, den Sie löschen; übergeben Sie force=true.nach einer Stunde ohne Renderings
409listen_session_limitIm Workspace laufen bereits drei Sitzungen von formfeed listen.sobald eine endet
409last_workspaceDer Workspace, den Sie löschen, ist der letzte der Organisation.nein
409storage_not_configuredDie Anfrage braucht den eigenen Bucket des Workspace (storage.key), aber der Workspace hat keine Speicherverbindung.nach dem Verbinden eines Buckets
410render_input_expiredDie Anfrage des Renderings wurde nicht aufbewahrt, oder ihre Aufbewahrungsfrist ist abgelaufen.nein
410listen_session_endedDie Sitzung von formfeed listen, die ein erneutes Senden oder eine Zustellung nennt, gibt es nicht mehr.nein
413file_too_largeEine hochgeladene Datei ist über ihrem Limit: 10 MB für die Dateibibliothek, 20 MB für ein Dokument zum Umwandeln oder eine Word- oder PowerPoint-Vorlage.nein
415file_type_unsupportedDie Datei ist kein Office-Dokument, das Formfeed umwandelt, enthält Makros, oder sie ist nicht die Art, die die Vorlage nimmt.nein
422channel_name_invalidDer Name eines Release Channels ist fehlerhaft oder reserviert.nein
422template_syntax_errorDie Vorlage ließ sich nicht kompilieren.nein
422template_runtime_errorDie Vorlage wurde kompiliert, ist aber bei der Ausführung mit Ihren Daten fehlgeschlagen.nein
422data_validation_errorDie Daten passen nicht zum Datenschema der Vorlage (bei validate_data: true).nein
422navigation_failedEin url-Rendering konnte die Seite nicht laden.nein
422page_limit_exceededDas PDF hat mehr Seiten, als der Plan erlaubt.nein
422output_too_largeDie gerenderte Datei oder ihr HTML ist größer als das Limit.nein
422source_not_foundEine Quelle eines PDF-Tools oder von post.merge_after existiert nicht, oder ihre Ausgabe ist nicht mehr vorhanden.nein
422source_invalidEine Quelle ist kein fertiges, lesbares PDF (bei einer Umwandlung: kein lesbares Office-Dokument).nein
422source_encryptedEine Quelle ist passwortgeschützt.nein
422office_document_invalidDer Container des Office-Dokuments ist beschädigt oder besteht eine Sicherheitsprüfung nicht.nein
422office_document_too_largeDas Office-Dokument entpackt sich zu mehr, als Formfeed verarbeitet, oder eine befüllte Vorlage wird zu groß.nein
422office_conversion_failedLibreOffice konnte das Dokument nicht umwandeln.nein
422unsupported_in_officeEine Word- oder PowerPoint-Vorlage verwendet etwas, das Office-Vorlagen nicht ausführen können, etwa ein Include.nein
422einvoice_data_invalidDer _invoice-Block einer E-Rechnung fehlt oder verletzt eine Regel, oder der Validator hat die fertige Datei abgelehnt.nein
422einvoice_profile_unsupportedDie Optionen der E-Rechnung nennen ein Profil oder ein flavour, das Formfeed nicht erzeugt.nein
422einvoice_display_mismatchMit display_check: "strict" zeigt das PDF einen Wert nicht, den das XML seiner E-Rechnung nennt.nein
422pdfua_validation_failedMit pdf.ua und strenger Prüfung verletzt die Datei eine Regel von PDF/UA-1; accessibility nennt die Regeln.nein
422storage_test_failedDas Testobjekt ließ sich nicht in den Bucket schreiben, die Speicherverbindung wurde deshalb nicht gespeichert; error enthält den Code des Anbieters.nach Korrektur von Schlüssel oder Bucket
429rate_limitedZu viele Anfragen, die Arbeit auslösen; warten Sie die Zeit aus Retry-After ab.ja
500tool_failedEin PDF-Tool oder die Validierung einer PDF/UA-Datei ist innerhalb von Formfeed fehlgeschlagen.einmal
500pdfa_conversion_failedDas PDF ließ sich nicht in ein gültiges PDF/A-3b umwandeln, das eine E-Rechnung sein muss.nein
500worker_exhaustedEin Fehler auf Seiten von Formfeed, den die Wiederholungen nicht behoben haben, oder ein unerwarteter Fehler.ja
501not_implementedReserviert für eine dokumentierte Funktion, die noch nicht verfügbar ist; heute antwortet nichts damit.nein
503region_unavailableDie Region hat gerade keinen freien Render-Platz, oder gar keinen Render-Dienst.nach Retry-After
503office_unavailableDer Office-Konverter ist ausgelastet oder nicht erreichbar.ja
503conformance_unavailableDer Dienst, der E-Rechnungen umwandelt und validiert und PDF/UA-Dateien validiert, ist ausgelastet oder nicht erreichbar.ja
504render_timeoutEin Schritt des Renderings hat länger gedauert als sein Limit.nur, wenn die Ursache vorbei ist

Innerhalb von /v1 können neue Codes hinzukommen. Behandeln Sie einen unbekannten Code anhand seines HTTP-Status.