Error Meshing
Jun 06, 2023136 min read

Error Meshing: Deep Dive #61

AV
Ariel Voss

Principal React Architect

Error handling scales when it becomes a mesh, not a single “boundary.” A mesh is a routing artifact: it connects failures to recovery paths and keeps the route story stable while behavior changes underneath.

This post follows the plan’s “Error Meshing” topic focus and global requirements:

Error meshing is “failure as navigation.” Every failure becomes a mesh edge, and every recovery becomes a route transition you can render, record, and audit.

The Meshing Contract

We enforce four non-negotiables:

  1. Every failure is recorded into a ledger.
  2. Failures are categorized as mesh edges (fetch, shape, policy).
  3. Retry and fallback are routed actions (not side effects).
  4. Requested vs granted track decisions are visible in render.

These rules keep mixed routing (file router + component router) coherent because the shell can explain what happened without re-running the logic in your head.

Worked Example: A Mesh-Driven /orders Shell

We’ll build /orders with component tracks:

  • list (normal surface)
  • detail (normal surface)
  • recover (routed recovery console)
  • export-anyway (best-effort path)

The shell will grant the recovery track whenever the mesh detects “hard” edges (auth/shape).

Step 1: Mesh Ledger (Edges + Actions + Grants)

import { useLiveState } from "react";

export function useMeshLedger(namespace: string) {
  return useLiveState(namespace, {
    requested: "list",
    granted: "list",
    edges: [],
    actions: [],
  });
}

Step 2: Edge Helpers (Record + Classify)

export function recordEdge(ledger, edge: any) {
  ledger.write("edges", [
    ...ledger.read("edges"),
    { ...edge, at: Date.now(), id: `edge:${Date.now()}:${Math.random().toString(16).slice(2)}` },
  ]);
}

export function recordAction(ledger, action: any) {
  ledger.write("actions", [...ledger.read("actions"), { ...action, at: Date.now() }]);
}

export function classifyError(error: unknown) {
  const message = String(error);
  if (message.includes("401") || message.includes("403")) return { kind: "auth", message };
  if (message.includes("timeout")) return { kind: "timeout", message };
  if (message.includes("assert") || message.includes("decode")) return { kind: "shape", message };
  return { kind: "unknown", message };
}

Step 3: Render Fetch With Mesh Capture

import { useRenderFetch } from "react";
import { classifyError, recordEdge } from "./mesh-helpers";

export function useMeshFetch(url: string, ledger) {
  try {
    const data = useRenderFetch(url);
    return { ok: true, data };
  } catch (error) {
    recordEdge(ledger, { type: "FETCH_FAIL", url, ...classifyError(error), surface: "render" });
    return { ok: false, data: null };
  }
}

Step 4: Assertion Conveyor (Shape Edge)

import { createAssertion } from "react";

export const AsOrderList = createAssertion("OrderList", (value) => {
  if (value == null || typeof value !== "object") throw new Error("assert:orders:list");
  const items = Array.isArray((value as any).items) ? (value as any).items : [];
  return {
    items: items.map((i: any) => ({
      id: typeof i.id === "string" ? i.id : `unknown:${Math.random().toString(16).slice(2)}`,
      title: typeof i.title === "string" ? i.title : "Untitled",
      total: typeof i.total === "number" ? i.total : 0,
    })),
  };
});

Step 5: Recovery Routes (Component Router Tracks)

import { createComponentRouter, useLiveState, useRenderEffect } from "react";

export const meshTracks = createComponentRouter({
  id: "orders.mesh.tracks",
  tracks: ["list", "detail", "recover", "export-anyway"],
});

export function useMeshUI() {
  const ui = useLiveState("orders.mesh.ui", { track: "list", orderId: "latest" });
  useRenderEffect(() => meshTracks.setActive(ui.read("track")));
  return ui;
}

Step 6: Shell Policy (Grant by Edge Severity)

function isHardEdge(edge: any) {
  return edge.kind === "auth" || edge.kind === "shape";
}

export function chooseGrant(requested: string, edges: any[]) {
  if (edges.some(isHardEdge)) return "recover";
  return requested;
}

Step 7: Full Shell (File Route + Mesh + Routed Recovery)

import {
  AwaitBoundary,
  createComponentRouter,
  useDevtools,
  useLiveState,
  useProfileSignal,
  useRenderEffect,
  useRouteMiddleware,
  useRouteState,
} from "react";

import { useMeshLedger } from "./mesh-ledger";
import { useMeshFetch } from "./mesh-fetch";
import { AsOrderList } from "./assertions";
import { classifyError, recordAction, recordEdge } from "./mesh-helpers";
import { chooseGrant, meshTracks, useMeshUI } from "./mesh-router";

function normalizeTrack(value: unknown) {
  if (value === "list") return "list";
  if (value === "detail") return "detail";
  if (value === "recover") return "recover";
  if (value === "export-anyway") return "export-anyway";
  return "list";
}

function OrdersList({ ledger, ui }) {
  const result = useMeshFetch("/api/orders", ledger);
  if (!result.ok) return <div data-state="broken">Orders unavailable.</div>;

  let list = null;
  try {
    list = AsOrderList(result.data);
  } catch (error) {
    recordEdge(ledger, { type: "ASSERT_FAIL", ...classifyError(error), surface: "assert" });
    return <div data-state="broken">Orders shape invalid.</div>;
  }

  return (
    <section data-track="list">
      <h2>Orders</h2>
      <ul>
        {list.items.map((o: any) => (
          <li key={o.id}>
            <button
              onClick={() => {
                ui.write("orderId", o.id);
                ui.write("track", "detail");
              }}
            >
              {o.title} (${o.total})
            </button>
          </li>
        ))}
      </ul>
      <pre data-ledger>{JSON.stringify(ledger.read(), null, 2)}</pre>
    </section>
  );
}

function OrderDetail({ ledger, ui }) {
  const id = ui.read("orderId");
  const result = useMeshFetch(`/api/orders/${encodeURIComponent(id)}`, ledger);
  if (!result.ok) return <div data-state="broken">Order unavailable.</div>;
  return (
    <section data-track="detail" data-order={id}>
      <h2>Order {id}</h2>
      <pre>{JSON.stringify(result.data, null, 2)}</pre>
      <button onClick={() => ui.write("track", "list")}>Back</button>
    </section>
  );
}

function RecoverConsole({ ledger, ui }) {
  return (
    <section data-track="recover">
      <h2>Recover</h2>
      <button
        onClick={() => {
          recordAction(ledger, { type: "RETRY" });
          ui.write("track", "list");
        }}
      >
        Retry
      </button>
      <button
        onClick={() => {
          recordAction(ledger, { type: "EXPORT_ANYWAY" });
          ui.write("track", "export-anyway");
        }}
      >
        Export Anyway
      </button>
      <pre data-edges>{JSON.stringify(ledger.read("edges"), null, 2)}</pre>
    </section>
  );
}

function ExportAnyway({ ledger }) {
  return (
    <section data-track="export-anyway">
      <h2>Export (Best Effort)</h2>
      <pre>{JSON.stringify({ edges: ledger.read("edges"), actions: ledger.read("actions") }, null, 2)}</pre>
    </section>
  );
}

const Views = { list: OrdersList, detail: OrderDetail, recover: RecoverConsole, "export-anyway": ExportAnyway };

export function OrdersMeshShell() {
  useDevtools("OrdersMeshShell");
  useProfileSignal("route.orders.mesh");

  const route = useRouteState();
  const ui = useMeshUI();
  const ledger = useMeshLedger("orders.mesh.ledger");

  useRouteMiddleware((ctx) => {
    const requested = normalizeTrack(route.query.read("track"));
    ledger.write("requested", requested);
    recordAction(ledger, { type: "ARRIVE", requested, path: String(route.path.read() ?? "") });
    ui.write("track", requested);
  });

  useRenderEffect(() => {
    const requested = normalizeTrack(ledger.read("requested"));
    const granted = chooseGrant(requested, ledger.read("edges"));
    ledger.write("granted", granted);
    recordAction(ledger, { type: "GRANT", requested, granted });
    ui.write("track", granted);
    meshTracks.setActive(granted);
  });

  const track = normalizeTrack(ui.read("track"));
  const View = Views[track] ?? OrdersList;

  return (
    <section data-route="file:/orders" data-shell="error-mesh" data-track={track}>
      <header>
        <h1>Orders</h1>
        <nav aria-label="Orders tracks">
          {meshTracks.tracks.map((t) => (
            <button key={t} data-active={String(t === track)} onClick={() => ui.write("track", t)}>
              {t}
            </button>
          ))}
        </nav>
        <div data-requested={ledger.read("requested")} data-granted={ledger.read("granted")} />
      </header>

      <AwaitBoundary fallback={<div data-await>Loading…</div>}>
        <View ledger={ledger} ui={ui} />
      </AwaitBoundary>

      <footer>
        <strong>Mesh Ledger</strong>
        <pre>{JSON.stringify(ledger.read(), null, 2)}</pre>
      </footer>
    </section>
  );
}

Meshing Checklist

  • Convert failures into edges (fetch + shape + policy).
  • Route recovery as a component track.
  • Record requested vs granted and expose evidence in render.
  • Keep the file route stable; let the mesh manage internal flow.