docs/reference/troubleshooting
リファレンス · Debugging

トラブルシューティング

ビルドエラーから状態のライフタイム、描画の不具合まで、最短経路で原因を特定します。

約 8 分で読めます

ビルドエラー

invalid fingerprint

テンプレートの fingerprint はそのまま再利用できません。build.zig.zon の .fingerprint 行を削除して zig build を一度実行し、Zig が出力した固有の値を書き戻してください。

import of file outside module path

フレームワーク内部のファイルに対して zig test を直接実行しないでください。zig build test-ui などリポジトリで定義されたテスト step を使います(コマンド一覧を参照)。

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

build.zig.zon で .zenit 依存が宣言されていること、そして executable の作成後に zenit.attach(zenit_dep, exe) を呼んでいることを確認してください。これが ui / zenit_app モジュールの追加、macOS ブリッジのコンパイル、システムフレームワークのリンクを行います。

build API field mismatch

まず zig version を実行してください。zenit は Zig 0.15.2 を必要とします(build.zig.zon の minimum_zig_version)。他のバージョンの build API はサポート対象外です。

-Dtest-mode=true has no effect

Zig の依存オプションは分離されています。b.dependency("zenit", ...) で .@"test-mode" と .@"e2e-port" を明示的に転送してください。templates/minimal-app/build.zig が参考になります。

実行時と状態

error.StateNotFound

明示的な ID を使う cx.handler(State, id, method) が、対応する state の作成前に呼ばれています。cx.bindState + cx.on を優先してください。状態ポインタを直接渡すので、ID を管理する必要がありません。

leaked ArrayList / HashMap at exit

bindState の状態は Cx が所有し、Cx の解放時に一緒に解放されます。T が pub の deinit(self: *T) を宣言していれば、フレームワークが自動で呼び出します。リークは通常、deinit が pub でないか、リソースがページのライフタイムに従うべきだったことを意味します。書き方は次のセクションを参照してください。

crash after switching pages

グローバル状態に前のページの *Node や *Scope を保存していないか確認してください。ページの Scope が dispose されると、これらのポインタはすべて無効になるため、同時にクリアする必要があります。

Invalid free after updating text

ノードの現在のテキストは、ノード自身が所有するコピーかもしれません。getText() で得た props の content を書き換えて setText で戻さないでください。try node.setTextContent(cx.allocator, "Updated") を使えば、文字列がコピーされ所有権も正しくマークされます。

状態の正しいクリーンアップ

状態に allocator フィールドを持たせ、pub の deinit 自身にクリーンアップを任せます。初期値はまだリソースを持っていてはいけません。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 });

scope.onCleanup を使うのは 2 つの場合だけです。クリーンアップ関数が pub の deinit でないとき、またはリソースが Cx 全体ではなく特定の Scope(ページ)のライフタイムに従うべきときです。

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

レイアウトと描画

state changed but the text did not

setText 自体が新旧のシグネチャを比較し、必要に応じて sizing / render dirty をマークするので、手動の markRenderDirty は不要です。テキストが更新されないのは、たいてい TextProps のコピーを書き換えて setText を呼んでいないか、表示中の値が対応する Signal を購読していないためです。ui.textFmt(cx, scope, fmt, .{ signals }, props) で Signal / Memo を直接購読する方法をおすすめします。

some colors ignore a theme switch

boxStyled / textStyled などのコンストラクタは on_theme hook を付けますが、cx.setTheme がそれを再実行するのは cx.root のサブツリーだけです。通常のノードやコンポーネントライブラリのスタイルは mount 時のスナップショットです。テーマ切り替え時に該当するツリーを再構築するか、Effect 内で cx.themeSignal(scope) を購読してスタイルを更新してください。cx.root 配下にないノードも更新されません。

clicks fall through an overlay’s empty area

インタラクションを持たない純粋に視覚的なコンテナは、既定で pass_through です。オーバーレイのルートノードのスタイル拡張に hit_behavior = .@"opaque" を設定するか、barrier を内蔵した Modal / Sheet を使ってください。

a huge invisible hit area in the window

ui.devtools.overlay をアタッチしてヒットしているノードを調べ、node.globalRect() でその画面上の rect を出力します。原因はたいてい親コンテナの fill / grow 設定か、大きすぎる絶対配置の範囲です。オーバーレイが非表示のときも、ヒットテストから外れているか確認してください。node.setDisplay(.none) で隠したサブツリーは、レイアウト・描画・ヒットテスト・Tab 移動からまとめて外れます。

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";

それでも解決しない場合

issue を報告するときは、少なくとも以下を添えてください。

  • ✓

    バージョン:zenit の revision、zig version、macOS のバージョン。

  • ✓

    再現:最小の再現コードと実行した build step。

  • ✓

    出力:最後の 1 行だけでなく、完全なエラー出力。

  • ✓

    描画の問題:スクリーンショットと、DevTools で確認した関連ノードのサイズ。

zenit · デュアルライセンスオープンソースプロジェクトは GPL-3.0-only のもとで無料で使えます。クローズドソースや商用製品には商用ライセンスが必要です。作者への連絡先:zongyi.xzy#gmail.com(# を @ に置き換え)zenit 5f9add5+wip 2026-09-30