Skip to Content
EntwicklerhandbuchDaemonFehler-Taxonomie & Behebung

Fehler-Taxonomie & Behebung

Übersicht

Die Fehlermodi des Daemons sind bewusst als geschlossene Unions definiert, sodass SDK-Konsumenten diese erschöpfend abfragen und Routen-Handler konsistente HTTP-Antworten erzeugen können. Dieses Dokument katalogisiert jede typisierte Fehlerklasse / -art auf drei Ebenen:

  1. packages/cli/src/serve/ — Grenzfehler an der HTTP-Schnittstelle (Auth, Arbeitsbereich-Dateisystem, Daemon-Host-Preflight).
  2. packages/acp-bridge/ — Bridge-/Mediator-Fehler an der Daemon-zu-ACP-Child-Grenze.
  3. packages/sdk-typescript/src/daemon/ — SDK-seitige Kapselung und strukturierte Fehlerfelder.

Die Drahtformate der Fehler sind in ../qwen-serve-protocol.md dokumentiert; dieses Dokument ergänzt Ursachen- und Behebungsanleitungen.

Dateisystem-Grenze (packages/cli/src/serve/fs/errors.ts)

FsError trägt { kind, message, status, cause? }. Die FsErrorKind-Union (14 Arten, standardmäßiger HTTP-Status):

ArtHTTPUrsacheBehebung
path_outside_workspace400Der aufgelöste Pfad verlässt den gebundenen Arbeitsbereich.Verwende einen Pfad innerhalb des workspaceCwd des Daemons; prüfe /capabilities.
symlink_escape400Das Ziel ist ein Symlink.Greife den aufgelösten Pfad direkt an; Symlinks werden bewusst abgelehnt.
path_not_found404ENOENT.Stelle sicher, dass die Datei existiert; beachte Groß-/Kleinschreibung unter Linux.
binary_file422Inhalt auf einer Text-Route als binär erkannt.Verwende GET /file/bytes für Rohbytes; die Text-Route lehnt Binärdateien ab.
file_too_large413Größer als MAX_READ_BYTES (256 KiB) oder MAX_WRITE_BYTES (5 MiB).Verwende Bytebereichs-Lesen; teile den Schreibvorgang auf.
hash_mismatch409Optimistische Nebenläufigkeit expectedSha256 fehlgeschlagen.Lese die Datei erneut und wiederhole mit dem neuen Hash.
file_already_exists409mode: 'create' gegen eine vorhandene Datei.Verwende mode: 'overwrite' oder wähle einen neuen Pfad.
text_not_found422Suchstring in POST /file/edit nicht in der Datei gefunden.Überprüfe den Suchstring erneut; meistens liegt es an Leerzeichen-/Kodierungsunterschieden.
ambiguous_text_match422Mehrere Treffer, obwohl nur einer erforderlich war.Füge dem Suchstring mehr umgebenden Kontext hinzu, um ihn eindeutig zu machen.
untrusted_workspace403Schreibversuch in einem nicht vertrauenswürdigen Arbeitsbereich.Markiere den Arbeitsbereich als vertrauenswürdig (Config.isTrustedFolder()) oder verwende runQwenServe statt direktem createServeApp-Einbett.
permission_denied403OS-Ebene EACCES / EPERM.Passe die Dateisystem-ACLs an; dies ist kein Sicherheitsalarm.
io_error503ENOSPC / EIO / EBUSY / ETXTBSY / ENAMETOOLONG / EMFILE / ENFILE.Host-seitiger betrieblicher Fix (Festplatte voll, fd-Erschöpfung); benachrichtige Betrieb, nicht Sicherheit.
internal_error500Ein Fehler ohne errno erreicht die Grenze.Melde einen Daemon-Fehler (Bug).
parse_error400 / 422Parsing-Fehler des Anfragetexts (400) oder Verstoß gegen Dienstebenen-Invarianten (422).Validiere den Anfragetext; überprüfe die SDK-Version.

Die Unterscheidung zwischen io_error und permission_denied ist bewusst, damit Überwachungspipelines auf errorKind routen können; das Zusammenführen von ENOSPC in permission_denied würde Sicherheitsverantwortliche für ein df -h-Problem alarmieren.

Bridge-Fehler (packages/acp-bridge/src/bridgeErrors.ts)

Typisierte Klassen, die von der Bridge/dem Mediator geworfen werden. Die meisten tragen einen HTTP-Status über den Switch des Routen-Handlers.

KlasseHTTPUrsacheBehebung
SessionNotFoundError404sessionId nicht in byId.Erstelle neu oder füge hinzu; die Sitzung könnte bereinigt worden sein.
WorkspaceMismatchError400POST /session cwdboundWorkspace des Daemons.Lasse cwd weg (verwendet den gebundenen) oder leite an einen Daemon weiter, der an dein cwd gebunden ist.
SessionLimitExceededError503byId.size >= maxSessions.Schließe alte Sitzungen; erhöhe --max-sessions.
InvalidClientIdError400X-Qwen-Client-Id außerhalb [A-Za-z0-9._:-]{1,128}.Bereinige die Client-ID.
InvalidSessionMetadataError400displayName > 256 Zeichen oder enthält Steuerzeichen.Kürze / bereinige.
InvalidSessionScopeError400Unbekannter sessionScope-Wert.Verwende 'single' oder 'thread'.
RestoreInProgressError409Gleichzeitiges loadSession / resumeSession.Warte + wiederhole.
WorkspaceInitConflictError409POST /workspace/init gegen eine vorhandene Datei ohne force.Übergib force: true oder wähle einen anderen Pfad.
WorkspaceInitPathEscapeError400Init-Pfad verlässt den Arbeitsbereich.Verwende einen Pfad innerhalb von workspaceCwd.
WorkspaceInitSymlinkError400Init-Pfad ist ein Symlink.Greife den aufgelösten Pfad an.
WorkspaceInitRaceError409TOCTOU-Wettlauf beim Init.Wiederhole.
McpServerNotFoundError404Neustart für einen unbekannten Server.Überprüfe den Servernamen in /workspace/mcp.
McpServerRestartFailedError502Neustart im ACP-Child fehlgeschlagen.Überprüfe die ACP-Child-Logs; kann auf einen defekten MCP-Server hinweisen.
InvalidPermissionOptionError400Draht-Abstimmungsversuch, CANCEL_VOTE_SENTINEL über optionId einzuschleusen.Stimme mit {outcome: 'cancelled'} anstelle einer optionId.
PermissionForbiddenError403Policy hat den Wähler abgelehnt (designated_mismatch / remote_not_allowed).Verwende die Client-ID des Urhebers (designated), registriere den Wähler vor (consensus) oder stimme über Loopback (local-only). Siehe 04-permission-mediation.md.
CancelSentinelCollisionError500Agent hat '__cancelled__' als legitime Option veröffentlicht.Agenten-Bug — ändere das Optionslabel auf etwas anderes als den Sentinel.
PermissionPolicyNotImplementedError500Angeforderte Policy ist in diesem Daemon nicht eingebaut.Aktualisiere den Daemon oder ändere policy.permissionStrategy.
BridgeChannelClosedError503ACP-Child-Kanal während des Aufrufs geschlossen.Verbinde erneut / wiederhole; prüfe session_died auf Ursache.
BridgeTimeoutError504Bridge-seitige Wanduhrzeit überschritten.Wiederhole; untersuche zugrundeliegende Langsamkeit.
MissingCliEntryError500Die qwen CLI-Einstiegsdatei fehlt (definiert in status.ts, nicht bridgeErrors.ts).Stelle sicher, dass die CLI-Installation vollständig ist; überprüfe, ob packages/cli/index.ts existiert.

Boot-Zeit-Konfigurationsfehler (packages/cli/src/serve/run-qwen-serve.ts)

KlasseWannBehebung
InvalidPolicyConfigErrorvalidatePolicyConfig() lehnt zusammengeführte Einstellungen ab: unbekanntes policy.permissionStrategy (validiert gegen SERVE_CAPABILITY_REGISTRY.permission_mediation.modes) oder nicht-positiv-ganzzahliges policy.consensusQuorum. Boot scheitert explizit.Korrigiere das betreffende Feld in settings.json. Die Klasse unterstützt instanceof; runQwenServe verwendet es, um Policy-Konflikte von Lese-I/O-Fehlern der Einstellungen zu unterscheiden, die auf Standardwerte zurückfallen.

Device-Flow-Auth (packages/cli/src/serve/auth/device-flow.ts)

KlasseWannHinweise
UpstreamDeviceFlowErrorDer Upstream-IdP gibt während des Pollings einen strukturierten Fehler zurück.oauthError wird mit sanitizeForStderr bereinigt, bevor es in stderr oder Audit-Hinweise eingefügt wird (CVE-2021-42574 / Trojan Source-Abwehr; siehe 12-auth-security.md).
DeviceFlowPollTimeoutErrorDer Registry-Wettlauftimer feuert, bevor der Anbieter antwortet.Anbieter-Code darf diesen Typ nicht werfen. Er wird für Tests exportiert, aber die Registry prüft pollTimedOut auf die Laufzeitmarke _isRegistryTimeout: boolean, nicht auf instanceof. Ein Anbieter, der new DeviceFlowPollTimeoutError(ms) importiert und wirft, durchläuft dennoch den generischen Anbieter-wirft-Audit-Pfad, weil _isRegistryTimeout standardmäßig false ist; nur die interne Factory makeRegistryPollTimeoutError(ms) setzt die Marke.

Daemon-Host-Fehlerarten (packages/acp-bridge/src/status.ts)

SERVE_ERROR_KINDS ist die geschlossene Aufzählung, die von Diagnosezellen und strukturierten Daemon-Fehlern verwendet wird:

ArtBedeutung
missing_binaryErforderliche lokale ausführbare Datei oder CLI-Einstieg konnte nicht aufgelöst werden.
blocked_egressAusgehende Netzwerkprüfung fehlgeschlagen.
auth_env_errorAuth-bezogene Umgebungsvariable, Anbieter oder Trust-Gate-Konfiguration ist ungültig.
init_timeoutDaemon-seitiger Initialisierungsschritt hat seine Wanduhrzeit überschritten.
protocol_errorACP/HTTP-Protokollkonflikt.
missing_fileErforderliche lokale Datei fehlt.
parse_errorFehler beim Parsen einer lokalen Datei oder Anfrage.
stat_failedFehler beim lokalen Dateisystem-stat.
budget_exhaustedMCP-Budget-Durchsetzung hat Erkennung oder einen Server-Eintrag abgelehnt.
mcp_budget_would_exceedMCP-Neustart oder -Mutation würde das konfigurierte Budget überschreiten.
mcp_server_spawn_failedStart oder Neustart des MCP-Servers fehlgeschlagen.
invalid_configMCP- oder Daemon-Konfiguration war ungültig.
prompt_deadline_exceededFrist der Prompt-Wanduhr abgelaufen.
writer_idle_timeoutSSE-Writer hat vor seinem Leerlauf-Timeout keine erfolgreichen Schreibvorgänge getätigt.

Diese werden über das errorKind der Preflight-Zelle an die Oberfläche gebracht, sodass Client-UIs strukturierte Behebungsmaßnahmen (anstelle von rohen Stacktraces) anzeigen.

Auth-Fehlerformate

StatusBodyWann
401{ error: 'Unauthorized' }Fehlender/falscher/kein-Schema Bearer-Token. Einheitlich bei fehlendem Header / falschem Schema / falschem Token, sodass Sondierung keine Unterscheidung ermöglicht.
401{ error: '...', code: 'token_required' }Mutations-Sperre auf strenger Route bei einem Daemon ohne Token auf Loopback. SDKs geben Hinweis “konfiguriere —token / —require-auth”.
403{ error: 'Request denied by CORS policy' }denyBrowserOriginCors hat eine Anfrage mit Origin-Header abgelehnt.
403{ error: 'Invalid Host header' }hostAllowlist hat den Host-Header abgelehnt (DNS-Rebinding-Abwehr).

Siehe 12-auth-security.md für das vollständige Auth-Modell.

Berechtigungsergebnisse (Drahtform vs. Audit-Überladung)

PermissionResolution hat zwei terminale Arten:

  • {kind: 'option', optionId} — eine Abstimmung hat gewonnen.
  • {kind: 'cancelled', reason: 'timeout' | 'session_closed' | 'agent_cancelled'} — die Anfrage wurde abgebrochen. Das Drahtformat ist einfach ({outcome: 'cancelled'}); das Audit-Log unterscheidet timeout / session_closed / voter-cancelled / agent-cancelled in decisionReason.type. Diese Überladung wird bewusst beibehalten, um den eingefrorenen permission.ts-Vertrag nicht zu brechen.

SDK-seitige Fehlerkapselung

DaemonClient gibt HTTP-Fehler als abgelehnte Promises mit dem geparsten Body als Ablehnungswert zurück. Methoden, die bei unbekannten Sitzungen auf 404 stoßen, lehnen mit {error, sessionId} ab; das SDK kapselt sie heute nicht in eine typisierte Klasse. Aufrufer sollten sich nicht auf instanceof Error plus .message.includes(...)-Abgleich verlassen; weiche stattdessen auf err.code oder err.kind aus dem Body aus. parseSseStream bricht den Iterator bei einem 16-MiB-Pufferüberlauf ab (defensive Grenze).

Workflow

Einen Fehler für einen Benutzer sichtbar machen

Authentifizierungsfehlermodi unterscheiden

Abhängigkeiten

  • Alle Fehlerklassen werden aus ihren jeweiligen Paketen exportiert; SDK-Konsumenten können im selben Node-Prozess mit instanceof gegen die bridgeErrors.ts-Typen prüfen. Über das Netzwerk hinweg wird anhand von body.code / body.kind / body.errorKind geroutet.

Einschränkungen & bekannte Grenzen

  • io_error vs permission_denied sind bewusst unterschiedlich. Nicht vermischen.
  • PermissionForbiddenError-Gründe (designated_mismatch / remote_not_allowed) sind überladen für die designated- und consensus-Policies; das Audit-Log unterscheidet sie präzise, die Drahtform jedoch nicht.
  • CancelSentinelCollisionError deutet auf einen Agent-seitigen Bug hin, kein Sicherheitsvorfall – die Bridge lehnt die Anfrage ab, anstatt stillschweigend zuzulassen, dass der Sentinel mit einer realen Option übereinstimmt.
  • SDK-seitige typisierte Fehler befinden sich noch in der Entwicklung. Aufrufer sollten über body-Felder routen, anstatt sich auf die JS-Klassenidentität über das Netzwerk zu verlassen.
  • internal_error sollte immer untersucht werden. Er signalisiert, dass ein FsError-Konstruktor mit einer für Nicht-errno-Pfade reservierten Fehlerart aufgerufen wurde (Programmierfehler); das cause-Feld im Antwort-Body kann die ursprüngliche Exception enthalten.

Referenzen

  • packages/cli/src/serve/fs/errors.ts (FsErrorKind, FsErrorStatus)
  • packages/acp-bridge/src/bridgeErrors.ts (jede typisierte Klasse)
  • packages/acp-bridge/src/status.ts (SERVE_ERROR_KINDS, ServeErrorKind)
  • packages/cli/src/serve/auth.ts (Authentifizierungs-Bodies)
  • Drahtreferenz: ../qwen-serve-protocol.md.
Last updated on