Zum Inhalt springen

Fehler und Scanergebnisse

Dies ist die Nachschlageseite für die Fehlerbehandlung: der Fehlertext, den jeder Endpunkt zurückgibt, die Codes, anhand derer sich Verzweigungen lohnen, und — am wichtigsten — die kanonischen Ergebnistabellen für Scans. „Keine Übereinstimmung“ ist ein Ergebnis und kein Übertragungsfehler, wird jedoch trotzdem mit einem HTTP-Fehlerstatus zurückgegeben. Code, der jede Nicht-2xx-Antwort als Fehler behandelt, meldet Ausfälle, die nie aufgetreten sind.

Endpunktspezifische Schemas finden Sie in der API-Referenz. Die Abläufe selbst werden unter Kennungen und in der Schnellstartanleitung beschrieben.

Jede fehlgeschlagene Anfrage gibt dasselbe JSON-Objekt zurück:

{
"code": "IDENTIFIER_NOT_FOUND",
"message": "No match in the 3 searched teams",
"status": 404,
"detail": { "outcome": "no_match", "teamsSearched": 3, "scan": { "scanId": "…", "fingerprintId": "…", "dustId": null } }
}
FeldTypBedeutung
codestringStabiler, maschinenlesbarer Code. Verzweigen Sie anhand dieses Werts. Analysieren Sie niemals message.
messagestringFür Menschen lesbarer Text, entsprechend Dust-Ctx-Locale lokalisiert. Formulierungen ändern sich, Codes nicht.
statusnumberEntspricht dem HTTP-Status.
detailobject, optionalFehlerspezifischer Kontext: Einzelheiten zur Validierung, Scanbeleg, Ergebnisklassifizierung und IDs von Konflikten.

status und der HTTP-Status stimmen immer überein, sodass Sie anhand eines der beiden Werte verzweigen können. Jede Antwort — ob erfolgreich oder fehlgeschlagen — enthält außerdem einen x-request-id-Header. Protokollieren Sie ihn; der Support verwendet ihn, um Ihre konkrete Anfrage zu finden.

CodeStatusWann
INVALID_REQUEST400Fehlerhaft formatierter Anfrageinhalt, Abfrageparameter oder Header. Einzelheiten zur Validierung stehen in detail.
INVALID_DATA400Die Anfrage konnte geparst werden, die Werte sind jedoch nicht verwendbar (beispielsweise Nutzdaten für die Identifizierung, die der Scanservice nicht lesen konnte).
UNAUTHORIZED401Fehlendes, abgelaufenes oder ungültiges Bearer-Token.
FORBIDDEN403Authentifiziert, aber dieser Kontext darf die Aktion nicht ausführen.
ATTRIBUTION_REQUIRED403Die Zuordnungsrichtlinie des Service Accounts ist required, und beim Schreibvorgang wurde kein Dust-Ctx-Declared-Actor übermittelt.
ORG_ID_REQUIRED / TEAM_ID_REQUIRED400Bei einem bereichsgebundenen Endpunkt fehlt ein Kontext-Header.
NOT_FOUND / NO_DATA_FOUND404In diesem Kontext ist kein entsprechender Datensatz sichtbar.
RATE_LIMITED429Warten Sie zunehmend länger und versuchen Sie es erneut.
THREAD_DATA_CONFLICT409Konflikt bei optimistischer Nebenläufigkeitskontrolle: Ihr expectedUpdatedAt ist veraltet. Lesen Sie die Daten erneut und wenden Sie Ihre Änderung nochmals an.
COMPOSITE_TAG_CONFLICT409Etikettenkonflikt — ein DUST befindet sich bereits auf einem anderen Etikett oder ist anderweitig verknüpft, eine Position auf der Etikettenrolle ist belegt oder die letzte Kennung eines Etiketts soll entfernt werden. detail.reason gibt den konkreten Grund an.
UNKNOWN_ERROR / SERVICE_ERROR500Serverseitiger Fehler. Versuchen Sie es mit zunehmender Wartezeit erneut; geben Sie die Anfrage-ID an, wenn der Fehler fortbesteht.
CodeStatusBedeutung
IDENTIFIER_NOT_FOUND404Definitiv keine Übereinstimmung: Jede durchsuchte Partition hat geantwortet, und es gab keine Übereinstimmung.
IDENTIFIER_NOT_BOUND404Die Kennung existiert, ist aber mit keinem Datensatz verknüpft (nur über eine Identifizierung anhand von tagId erreichbar).
IDENTIFIER_ALREADY_BOUND409Die Verknüpfung wurde abgelehnt — diese Kennung (oder ihr Etikett) befindet sich bereits auf einem anderen Datensatz. detail.compositeTagId bezeichnet das Etikett.
IDENTIFIER_VERIFY_FAILED500Die Verifizierung einer einzelnen Kennung ergab keine Übereinstimmung, oder die angegebene Kennung ist nicht mit diesem Datensatz verknüpft.
SCAN_AMBIGUOUS_MATCH409Zwei oder mehr unterschiedliche registrierte DUSTs stimmten überein, und beide sind im durchsuchten Umfang verknüpft. Mit derselben Aufnahme kann der Vorgang nicht erfolgreich wiederholt werden.
SCAN_SEARCH_INCOMPLETE503Einige Partitionen meldeten „keine Übereinstimmung“, andere konnten jedoch nicht durchsucht werden. Dies ist keine definitive fehlende Übereinstimmung — versuchen Sie es erneut.
SCAN_LOW_KEYPOINTS / SCAN_NO_KEYPOINTS400Die Aufnahme selbst wurde abgelehnt: Sie enthält zu wenige brauchbare Details. Scannen Sie erneut; verwenden Sie nicht dasselbe Bild nochmals.
SCAN_IDENTICAL_SCAN400Das übermittelte Bild besteht aus exakt denselben Bytes wie eine frühere Aufnahme. Erstellen Sie eine neue Aufnahme.
SCAN_EXTRACTION_FAILURE500Die Extraktion ist bei einem ansonsten akzeptierten Bild fehlgeschlagen.
SCAN_ROUTING_UNAVAILABLE503Der Vorgang ist für diese Organisation nicht verfügbar (beispielsweise weil ein Modul nicht aktiviert ist), oder seine Route ist ausgefallen.
SCAN_BACKEND_UNAVAILABLE503Das Scan-Backend ist vorübergehend nicht verfügbar. Die Aufnahme war in Ordnung — versuchen Sie es erneut, ohne erneut zu scannen.

POST /api/v1/tags/identify hat acht mögliche Ergebnisse. Drei davon werden mit 200 zurückgegeben; die übrigen werden mit Fehlerstatus zurückgegeben und sind dennoch Ergebnisse. Diese Tabelle ist die maßgebliche Quelle sowohl für Integrationen durch Menschen als auch durch Agents — dieselbe Tabelle erscheint in den Skills dice-api-integration und dust-go-connect-integration.

ErgebnisHTTPAntwortinhaltBedeutungVorgehen
Identifizierter Datensatz200{ type: "identified", identified: { tag, thread, … }, scan? }Genau eine verknüpfte Kennung stimmte überein.Öffnen Sie den Datensatz. scan.dustId ist der aufgelöste DUST.
Mehrere Kandidaten200{ type: "matches", matches: [ … ], scan? }Mehr als eine verknüpfte Kennung stimmte überein, oder die Übereinstimmung muss eindeutig bestimmt werden.Zeigen Sie die Kandidaten an und identifizieren Sie erneut anhand von tagId (tagType: "ANY"). scan.dustId ist null; jeder Kandidat enthält seinen eigenen Wert.
Nicht verknüpftes Etikett200{ type: "label", label: { label, tags }, scan? }Der Scan wurde einem Bestandteil eines Etiketts im Bestand Ihres Teams zugeordnet, das noch mit keinem Datensatz verknüpft ist.Bieten Sie an, das Etikett zu verknüpfen. Dies ist keine fehlende Übereinstimmung.
Keine Übereinstimmung404code: "IDENTIFIER_NOT_FOUND", detail.outcome: "no_match"Jede durchsuchte Partition hat geantwortet, und es gab keine Übereinstimmung. detail.teamsSearched gibt den Umfang an.Zeigen Sie „nicht gefunden“ an. Melden Sie keinen Dienstausfall. Der Beleg befindet sich unter detail.scan.
Unvollständige Suche503code: "SCAN_SEARCH_INCOMPLETE", detail.outcome: "search_incomplete"Einige Partitionen meldeten „keine Übereinstimmung“, andere waren nicht erreichbar. detail.teamsSearched, detail.teamsUnreachable, detail.orgsUnreachable.Versuchen Sie es erneut. Stellen Sie dies niemals als „nicht gefunden“ dar — das Objekt könnte durchaus registriert sein.
Mehrdeutige Übereinstimmung409code: "SCAN_AMBIGUOUS_MATCH", detail.outcome: "ambiguous", detail.candidates, detail.boundCandidates, detail.attemptsZwei oder mehr verknüpfte DUSTs stimmten mit hoher Sicherheit überein. Die Plattform hat dieselbe Aufnahme zweimal durchsucht, bevor sie dieses Ergebnis zurückgab.Zeigen Sie das Ergebnis zusammen mit scan.scanId an und wenden Sie sich an DUST Identity. Eine neue Aufnahme desselben Objekts wird die Mehrdeutigkeit nicht beheben.
Aufnahme abgelehnt400code: "SCAN_LOW_KEYPOINTS" / "SCAN_NO_KEYPOINTS" / "SCAN_IDENTICAL_SCAN", detail.outcome: "quality_reject"Das Bild konnte nicht verwendet werden. Die Ablehnung aufgrund der Qualität hat Vorrang vor jedem anderen Partitionsergebnis.Bitten Sie den Bediener, erneut zu scannen. Das Bild wird als abgelehnter Scan gespeichert; detail.scan.fingerprintId ist null.
Kennung nicht verknüpft404code: "IDENTIFIER_NOT_BOUND"Nur bei einer Identifizierung anhand von tagId (tagType: "ANY"): Die Kennung existiert, hat aber keinen Datensatz.Bieten Sie an, sie zu verknüpfen.

detail.outcome ist die vom Server verwendete Klassifizierung und bleibt stabil: no_match, search_incomplete, ambiguous, quality_reject. Verzweigen Sie zuerst anhand von code, und lesen Sie detail.outcome, wenn Sie die genauere Unterscheidung benötigen.

Verzweigung anhand eines Identifizierungsergebnisses

Abschnitt betitelt „Verzweigung anhand eines Identifizierungsergebnisses“
// Runs on your SERVER (it holds the bearer token).
const response = await fetch(`${apidUrl}/api/v1/tags/identify`, {
method: "POST",
headers: { Authorization: `Bearer ${token}`, "Dust-Ctx-Org-Id": organizationId },
body: form,
});
const body = await response.json();
if (response.ok) {
switch (body.type) {
case "identified": return { kind: "thread", thread: body.identified.thread };
case "matches": return { kind: "candidates", candidates: body.matches };
case "label": return { kind: "unbound-label", label: body.label };
default: throw new Error(`Unknown identify result type: ${body.type}`);
}
}
switch (body.code) {
case "IDENTIFIER_NOT_FOUND":
// An answer, not an outage.
return { kind: "no-match", scanId: body.detail?.scan?.scanId ?? null };
case "SCAN_SEARCH_INCOMPLETE":
case "SCAN_BACKEND_UNAVAILABLE":
return { kind: "retry", scanId: body.detail?.scan?.scanId ?? null };
case "SCAN_LOW_KEYPOINTS":
case "SCAN_NO_KEYPOINTS":
case "SCAN_IDENTICAL_SCAN":
return { kind: "rescan", scanId: body.detail?.scan?.scanId ?? null };
case "SCAN_AMBIGUOUS_MATCH":
return { kind: "ambiguous", scanId: body.detail?.scan?.scanId ?? null };
default:
throw new Error(`${body.code}: ${body.message}`);
}

POST /api/v1/tags/verify verhält sich unterschiedlich, je nachdem, wie viele mögliche Kennungen Sie in tags senden, da eine einzelne mögliche Kennung eine Ja/Nein-Frage darstellt, mehrere hingegen eine Suche:

Länge von tagsÜbereinstimmungKeine Übereinstimmung
Genau eine200 mit { tag, scan? }IDENTIFIER_VERIFY_FAILED (500), Beleg unter detail.scan
Zwei oder mehr200 mit { success: true, verifiedTag, attemptedCount, failedCount, scan? }200 mit { success: false, attemptedCount, failedCount, error, scan? }

Eine fehlgeschlagene Massenverifizierung ist daher ein erfolgreicher HTTP-Aufruf mit success: false. Lesen Sie immer success, wenn Sie mehr als eine mögliche Kennung senden, und leiten Sie die Authentizität niemals allein aus response.ok ab.

tags ist bei jeder Verifizierung erforderlich. Es ist ein Array aus Objekten und kein Array aus IDs:

[{ "tagId": "8f2b…", "tagType": "DUST" }]

Jeder Vorgang, bei dem ein Bild übermittelt wird — Extraktion, Verknüpfung, Identifizierung, Verifizierung oder Manipulationsanalyse — gibt einen Scanbeleg zurück, der angibt, was gespeichert wurde:

{ "scanId": "…", "fingerprintId": "…", "dustId": "…" }
  • Bei Erfolg befindet er sich auf der obersten Ebene unter scan.
  • Bei einem gespeicherten, aber negativen Ergebnis befindet er sich unter detail.scan — bei einer fehlenden Übereinstimmung während der Verifizierung, keiner Übereinstimmung während der Identifizierung, einer wegen eines Duplikats abgelehnten Verknüpfung sowie einer Ablehnung aufgrund der Qualität (bei der fingerprintId den Wert null hat, weil nichts Brauchbares extrahiert wurde).

Erfassen Sie scanId in beiden Fällen. Sie ist über Algorithmusmigrationen hinweg die stabile Identität der Aufnahme und wird vom Support benötigt, um das Bild hinter einem strittigen Ergebnis zu prüfen. Nur wenn die Plattform ein Bild überhaupt nicht dekodieren konnte, wird nichts gespeichert; in diesem Fall gibt es keinen Beleg.

const receipt = response.ok ? body.scan : body.detail?.scan;
if (receipt) await recordScan(receipt.scanId, receipt.fingerprintId, receipt.dustId);

dustId bezeichnet den Wert, den die Plattform an Sie zurückgegeben hat, und niemals eine interne Rohübereinstimmung: Bei einer fehlenden Übereinstimmung, keiner Übereinstimmung, einer Extraktion, einer Manipulationsanalyse und einer Identifizierung mit mehreren Kandidaten ist der Wert null.

Bearer-Tokens sind kurzlebig, und es gibt kein Refresh-Token — Sie tauschen die Anmeldedaten erneut ein. Ein abgelaufenes Token führt zu einem gewöhnlichen 401 UNAUTHORIZED und ist nicht von einem widerrufenen Token zu unterscheiden; behandeln Sie daher beide Fälle gleich:

  1. Erneuern Sie das Token proaktiv. GET /api/auth/token gibt expiresIn (Sekunden) und expiresAt (ISO 8601) zurück, wenn das Token einen Ablaufanspruch enthält. Tauschen Sie die Anmeldedaten mit einem Zeitpuffer erneut ein (60 Sekunden sind komfortabel); codieren Sie die Gültigkeitsdauer niemals fest ein.
  2. Wiederholen Sie die Anfrage bei 401 einmal. Sowohl Uhrzeitabweichungen als auch ein Widerruf während der Gültigkeitsdauer führen zu diesem Status. Einmaliges Erneuern und Wiederholen ist angemessen; eine Schleife nicht.
  3. Erzeugen Sie das Token für jede Anfrage aus einem Cache, statt dies nur einmal beim Prozessstart zu tun, damit ein Auftrag, der länger als ein Token läuft, nicht mittendrin fehlschlägt.

Eine vollständige Implementierung finden Sie unter Authentifizierung → Token-Ablauf und Erneuerung.

SituationDieselbe Anfrage erneut versuchen?Hinweise
401 UNAUTHORIZEDJa, einmal nach dem erneuten Eintauschen der AnmeldedatenMehr als ein Versuch bedeutet, dass die Anmeldedaten selbst falsch sind.
429 RATE_LIMITEDJa, mit zunehmender Wartezeit
503 SCAN_SEARCH_INCOMPLETE / SCAN_BACKEND_UNAVAILABLEJa — die Aufnahme ist in OrdnungLassen Sie den Bediener nicht erneut scannen.
503 SCAN_ROUTING_UNAVAILABLENeinDer Vorgang ist für diese Organisation nicht verfügbar; wenden Sie sich an DUST Identity.
400 SCAN_LOW_KEYPOINTS / SCAN_NO_KEYPOINTS / SCAN_IDENTICAL_SCANNein — stattdessen erneut scannenDieselben Bytes werden erneut abgelehnt.
404 IDENTIFIER_NOT_FOUNDNeinEs handelt sich um ein Ergebnis.
409 SCAN_AMBIGUOUS_MATCHNeinDer Vorgang wurde bereits serverseitig wiederholt; detail.attempts gibt dies an.
409 THREAD_DATA_CONFLICTErneut lesen, erneut anwenden und anschließend schreibenWiederholen Sie den Schreibvorgang nicht blind — Sie würden die Änderung einer anderen Person überschreiben.
5xx UNKNOWN_ERRORJa, bei idempotenten Lesevorgängen mit zunehmender WartezeitPrüfen Sie bei Schreibvorgängen vor einer Wiederholung, ob der Schreibvorgang ausgeführt wurde.