Theme
Version
GitHub PyPI Discord

Error boundary

Use this pattern when one part of a page, such as a widget that calls an outside service, may fail to render and the rest of the page should still appear. Wrap that part in <c-error-fallback>, and if it raises an error while rendering, Citry shows the fallback text in its place.

"""A widget that fails on demand, to demonstrate error boundaries."""

from typing import Any

from citry import Component

class FlakyWidget(Component):
    """Renders normal content, or raises when ``fail`` is true."""

    class Kwargs:
        label: str
        fail: bool = False

    class Slots:
        pass

    def template_data(
        self,
        kwargs: Kwargs,
        slots: Slots,
    ) -> dict[str, Any]:
        if kwargs.fail:
            # Raised during render, so the surrounding
            # <c-error-fallback> catches it.
            raise ValueError("FlakyWidget was told to fail")
        return {"label": kwargs.label}

    template = """
      <div class="flaky">
        <strong>{{ label }}</strong>
        <p class="flaky__ok">Loaded cleanly.</p>
      </div>
    """

    css = """
      .flaky {
        padding: 0.75rem 1rem;
        border: 1px solid #2da44e;
        border-radius: 8px;
        background: #effef1;
      }
      .flaky__ok {
        margin: 0.35rem 0 0;
        color: #1a7f37;
      }
    """

Both widgets are the same component. The second one raises ValueError in template_data(), so its boundary shows "Could not load this widget." The first widget, in its own boundary, renders normally.

To use markup as the fallback, nest boundaries, or see what happens to an error that no boundary catches, see Error boundaries.