docs/reference/troubleshooting
Referenz · Debugging

Fehlerbehebung

Von Build-Fehlern über die Lebensdauer von Zustand bis zu Rendering-Fehlern – der kürzeste Weg zur Ursache.

8 Min. Lesezeit

Build-Fehler

invalid fingerprint

Der Fingerprint einer Vorlage lässt sich nicht wiederverwenden. Löschen Sie die Zeile .fingerprint in build.zig.zon, führen Sie einmal zig build aus und fügen Sie den eindeutigen Wert ein, den Zig ausgibt.

import of file outside module path

Führen Sie zig test nicht direkt auf Framework-interne Dateien aus. Verwenden Sie die Test-Steps des Repos wie zig build test-ui (siehe Befehle).

@import("ui") / @import("zenit_app") not found

Prüfen Sie, ob build.zig.zon die Abhängigkeit .zenit deklariert und ob Sie nach dem Erstellen des Executables zenit.attach(zenit_dep, exe) aufrufen – es fügt die Module ui / zenit_app hinzu, kompiliert die macOS-Bridges und linkt die System-Frameworks.

build API field mismatch

Führen Sie zuerst zig version aus. zenit benötigt Zig 0.15.2 (minimum_zig_version in build.zig.zon); die Build-APIs anderer Versionen werden nicht unterstützt.

-Dtest-mode=true has no effect

Zig isoliert Abhängigkeitsoptionen. Reichen Sie .@"test-mode" und .@"e2e-port" in b.dependency("zenit", ...) explizit weiter, wie es templates/minimal-app/build.zig tut.

Laufzeit und Zustand

error.StateNotFound

Ein cx.handler(State, id, method) mit expliziter ID lief, bevor dieser Zustand existierte. Verwenden Sie besser cx.bindState + cx.on: Sie übergeben den Zustandszeiger direkt, es gibt keine IDs zu verwalten.

leaked ArrayList / HashMap at exit

Zustand aus bindState gehört dem Cx und wird mit ihm freigegeben; deklariert T ein pub deinit(self: *T), ruft das Framework es automatisch auf. Ein Leak bedeutet meist, dass deinit nicht pub ist oder die Ressource der Lebensdauer einer Seite hätte folgen sollen. Siehe nächsten Abschnitt.

crash after switching pages

Suchen Sie nach einem *Node oder *Scope der vorherigen Seite im globalen Zustand. Sobald der Scope der Seite freigegeben ist, sind diese Zeiger ungültig und müssen mit ihm gelöscht werden.

Invalid free after updating text

Der aktuelle Text des Knotens kann eine Kopie sein, die dem Knoten gehört. Ändern Sie nicht content an Props aus getText(), um sie per setText zurückzugeben; verwenden Sie try node.setTextContent(cx.allocator, "Updated"), das den String kopiert und den Besitz korrekt markiert.

Zustand richtig aufräumen

Legen Sie im Zustand ein allocator-Feld an und überlassen Sie das Aufräumen einem pub deinit. Der Anfangswert darf noch keine Ressourcen besitzen – allozieren Sie nach bindState.

state_deinit.zig
const Editor = struct {
    allocator: std.mem.Allocator,
    lines: std.ArrayList([]const u8) = .empty,

    // pub: the Cx calls this automatically when it frees the state.
    pub fn deinit(self: *Editor) void {
        self.lines.deinit(self.allocator);
    }
};

// The initial value must not own resources yet; allocate after binding.
const editor = try cx.bindState(Editor, .{ .allocator = cx.allocator });

Greifen Sie nur dann zu scope.onCleanup, wenn das Aufräumen kein pub deinit ist oder die Ressource einem Scope (einer Seite) statt dem ganzen Cx folgen muss.

scope_cleanup.zig
// Resources that must follow a page (Scope), not the whole window (Cx).
const PageCache = struct {
    allocator: std.mem.Allocator,
    map: std.StringHashMapUnmanaged(u32) = .empty,

    // Not named `pub fn deinit`: the Cx would call it again and double-free.
    fn release(self: *PageCache) void {
        self.map.deinit(self.allocator);
    }
};

const cache = try cx.bindState(PageCache, .{ .allocator = cx.allocator });
try scope.onCleanup(PageCache, cache, PageCache.release);

Layout und Zeichnen

state changed but the text did not

setText vergleicht bereits alte und neue Signatur und markiert sizing / render dirty bei Bedarf – kein manuelles markRenderDirty nötig. Veralteter Text bedeutet meist, dass eine TextProps-Kopie ohne Aufruf von setText geändert wurde oder der angezeigte Wert sein Signal nie abonniert hat. Verwenden Sie besser ui.textFmt(cx, scope, fmt, .{ signals }, props), um Signals / Memos direkt zu abonnieren.

some colors ignore a theme switch

boxStyled / textStyled und Co. hängen einen on_theme-Hook an, und cx.setTheme spielt diese nur im Teilbaum von cx.root erneut ab; einfache Knoten und Komponenten-Styles sind Momentaufnahmen vom Mount. Bauen Sie diese Bäume beim Theme-Wechsel neu auf, oder abonnieren Sie cx.themeSignal(scope) in einem Effect und stylen Sie neu; Knoten, die nicht unter cx.root hängen, werden ebenfalls nicht aktualisiert.

clicks fall through an overlay’s empty area

Rein visuelle Container ohne Interaktion sind standardmäßig pass_through. Setzen Sie hit_behavior = .@"opaque" in der Style-Erweiterung der Overlay-Wurzel – oder verwenden Sie Modal / Sheet, die ihre eigene Barriere mitbringen.

a huge invisible hit area in the window

Hängen Sie ui.devtools.overlay an, um den getroffenen Knoten zu untersuchen, und geben Sie sein Bildschirm-Rect mit node.globalRect() aus. Übliche Ursache ist ein fill-/grow-Sizing des Elternknotens oder eine zu große absolute Position; prüfen Sie bei ausgeblendeten Overlays, ob sie aus dem Hit-Testing entfernt sind – ein mit node.setDisplay(.none) ausgeblendeter Teilbaum verlässt Layout, Zeichnen, Hit-Testing und Tab-Navigation als Ganzes.

opaque_overlay.zig
// Plain visual containers are pass-through by default.
// Make an overlay root swallow clicks on its empty area:
(try panel.style.ensureExtFallible(cx.allocator)).hit_behavior = .@"opaque";

Immer noch festgefahren

Wenn Sie ein Issue melden, fügen Sie mindestens Folgendes bei:

  • ✓

    Versionen: die zenit-Revision, zig version und Ihre macOS-Version.

  • ✓

    Reproduktion: ein minimales Beispiel und der ausgeführte Build-Step.

  • ✓

    Ausgabe: die vollständige Fehlerausgabe, nicht nur die letzte Zeile.

  • ✓

    Rendering-Probleme: ein Screenshot sowie die Größen der betroffenen Knoten aus DevTools.

zenit · DoppellizenzKostenlos für Open-Source-Projekte unter GPL-3.0-only; Closed-Source- oder kommerzielle Produkte benötigen eine kommerzielle Lizenz.Kontakt zum Autor: zongyi.xzy#gmail.com (# durch @ ersetzen)zenit 5f9add5+wip 2026-09-30