Skip to content

Diagnostics

Developer-mode warnings and error reporting. This module powers the feedback you get while developing: [PN] WARN messages for suspicious props and styles, the HookOrderError raised on conditional hooks, and the RedBox overlay that surfaces uncaught errors from renders, effects, and event handlers.

Dev mode is enabled automatically by pn start / pn preview and in the debug builds pn run produces, or explicitly with the PN_DEV=1 environment variable. In production builds every check in this module is skipped, so shipping apps pay no overhead.

import pythonnative as pn

if pn.diagnostics.is_dev():
    pn.diagnostics.warn("fetching from a staging endpoint")

Most apps never call this module directly; it exists so framework code (and custom component libraries) can report problems in a way that reaches the developer instead of disappearing into a log.

Developer diagnostics: dev mode, warnings, and error reporting.

PythonNative distinguishes dev mode (the pn preview window, pn run with hot reload, or any process with PN_DEV=1) from production. Dev mode turns on:

  • Validation warnings (warn / warn_once): unknown style keys, duplicate list keys, and similar mistakes are printed once with a suggestion instead of failing silently.
  • Hook-order checking: calling hooks conditionally corrupts slot state; in dev mode the mismatch raises a HookOrderError immediately instead of cross-wiring state.
  • The RedBox: uncaught errors from render, effects, and event handlers are routed to the screen host, which presents a full-screen error overlay (see pythonnative.hosts) instead of crashing or swallowing the traceback.

In production none of this runs: validation is skipped, hook-order checks are skipped, and errors propagate exactly as raised.

This module has no dependencies on the rest of PythonNative, so any module (hooks, reconciler, events) may import it freely.

Classes:

Name Description
HookOrderError

Raised in dev mode when hooks are called in a different order than the previous render.

Functions:

Name Description
set_dev_mode

Explicitly enable or disable dev mode for this process.

reset_dev_mode

Return to the mode the PN_DEV environment variable selects.

is_dev

Return whether dev diagnostics are active.

log

Print a framework trace line ([PN] message) in dev mode.

warn

Print a dev warning and record it in the warning log.

warn_once

Like warn, but at most once per key.

swallowed

Surface a suppressed native-backend exception (dev mode only).

get_warnings

Return a snapshot of the recorded warnings (oldest first).

clear_warnings

Drop all recorded warnings and dedupe keys (test helper).

set_error_reporter

Register or unregister owner's RedBox reporter.

report_error

Route exc to the active RedBox reporter (dev mode only).

HookOrderError

Bases: RuntimeError

Raised in dev mode when hooks are called in a different order than the previous render.

Hooks map to state slots by call order, so calling them inside conditionals or loops (or returning early between hook calls) silently cross-wires state in production. Dev mode detects the mismatch and raises this error with the offending component and slot so the bug is caught at the source.

set_dev_mode

set_dev_mode(enabled: bool) -> None

Explicitly enable or disable dev mode for this process.

Called automatically by pn preview and by the screen host's enable_hot_reload (which the device templates invoke on debug builds). An explicit call wins over the PN_DEV environment variable.

Parameters:

Name Type Description Default
enabled bool

True to turn on dev diagnostics.

required

reset_dev_mode

reset_dev_mode() -> None

Return to the mode the PN_DEV environment variable selects.

is_dev

is_dev() -> bool

Return whether dev diagnostics are active.

An explicit set_dev_mode call wins; otherwise the PN_DEV environment variable, read when this module is imported, decides (default False).

log

log(message: str) -> None

Print a framework trace line ([PN] message) in dev mode.

The reconciler and screen hosts call this at phase boundaries (mount, re-render, RedBox) so a dev console shows what the runtime is doing. No-op in production.

Parameters:

Name Type Description Default
message str

The trace text.

required

warn

warn(message: str) -> None

Print a dev warning and record it in the warning log.

No-op in production. Warnings are prefixed with [PN] WARN on stderr and retained (most recent 200) for inspection via get_warnings.

Parameters:

Name Type Description Default
message str

Human-readable description of the problem, ideally with a suggestion for the fix.

required

warn_once

warn_once(message: str, key: Optional[str] = None) -> None

Like warn, but at most once per key.

Use for per-render validation (style keys, list keys) so a warning fires once instead of sixty times a second.

Parameters:

Name Type Description Default
message str

The warning message.

required
key Optional[str]

Dedupe key, e.g. "style:Text:font_siez". Defaults to the message itself.

None

swallowed

swallowed(context: str) -> None

Surface a suppressed native-backend exception (dev mode only).

The native view/module backends intentionally degrade gracefully in production: a failed style application or a missing OS API must not crash the app. Call this from the except block instead of pass so that, in dev mode, each suppression is reported once per call site instead of disappearing.

Parameters:

Name Type Description Default
context str

Where the suppression happened, e.g. "ios.TextHandler._apply".

required

get_warnings

get_warnings() -> List[str]

Return a snapshot of the recorded warnings (oldest first).

clear_warnings

clear_warnings() -> None

Drop all recorded warnings and dedupe keys (test helper).

set_error_reporter

set_error_reporter(
    owner: Any,
    reporter: Optional[
        Callable[[BaseException, str], None]
    ],
) -> None

Register or unregister owner's RedBox reporter.

Parameters:

Name Type Description Default
owner Any

Any object identifying the registration (a screen host); keyed by id(owner).

required
reporter Optional[Callable[[BaseException, str], None]]

reporter(exc, phase) callable, or None to unregister the owner's reporter.

required

report_error

report_error(
    exc: BaseException, phase: str = "runtime"
) -> bool

Route exc to the active RedBox reporter (dev mode only).

Parameters:

Name Type Description Default
exc BaseException

The exception to display.

required
phase str

Where it came from: "render", "effect", "event", or "async".

'runtime'

Returns:

Type Description
bool

True when a reporter accepted the error, False when no

bool

reporter is registered (or dev mode is off), in which case the

bool

caller should fall back to its default behavior.

Next steps