---
title: "Fehlerbehebung — zenit Zig UI Doku"
description: "Von Build-Fehlern über die Lebensdauer von Zustand bis zu Rendering-Fehlern – der kürzeste Weg zur Ursache."
url: https://zenit.z.express/de/docs/reference/troubleshooting
language: de
alternate_en: https://zenit.z.express/docs/reference/troubleshooting.md
alternate_zh: https://zenit.z.express/zh/docs/reference/troubleshooting.md
alternate_es: https://zenit.z.express/es/docs/reference/troubleshooting.md
alternate_ja: https://zenit.z.express/ja/docs/reference/troubleshooting.md
alternate_ko: https://zenit.z.express/ko/docs/reference/troubleshooting.md
alternate_fr: https://zenit.z.express/fr/docs/reference/troubleshooting.md
project: zenit v0.1.0-alpha (Zig 0.15.2, macOS)
source: https://github.com/version-next/zenit
---

# Fehlerbehebung

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

## 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](https://zenit.z.express/de/docs/reference/commands)).

**@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`

```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`

```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);
```

> WARNING
> 
> **Registrieren Sie deinit nicht doppelt.** Hat T bereits ein pub `deinit`, führt die Registrierung derselben Funktion mit `scope.onCleanup` zu doppelter Freigabe: einmal beim Freigeben des Scopes und erneut, wenn der Cx den Zustand freigibt.

## 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](https://zenit.z.express/de/components/modal) / [Sheet](https://zenit.z.express/de/components/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`

```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.
