PATTERN Cited by 1 source
Error isolation per feature wrapper¶
When to use¶
You are composing a response from many independent units (features, widgets, panels) and you want:
- A failure in one unit to drop only that unit, not the whole response.
- Explicit opt-in for units that should fail the whole response (e.g. the primary feature on a page).
- Centralised error telemetry keyed by unit and owner, not scattered per-feature try/except blocks.
The pattern¶
Every unit is invoked through a decorator that catches exceptions. On catch:
- If the unit is marked essential, re-raise (the whole response fails).
- Otherwise, log the exception with unit identity, owner metadata, and request context, and return a neutral value (empty list, None, sentinel) so the composer can continue.
def error_decorator(f: F) -> F:
@wraps(f)
def wrapper(self, *args, **kwargs):
try:
return f(self, *args, **kwargs)
except Exception as e:
if self._is_essential_provider:
raise
log_error(exception=e, context=self._context)
return []
return cast(F, wrapper)
class ErrorHandlingExecutionContext:
def __init__(self, wrapped_element: ProviderBase) -> None:
self._wrapped_element: ProviderBase = wrapped_element
self._context: Context = self._wrapped_element.context
self._is_essential_provider: bool = (
self._wrapped_element.IS_ESSENTIAL_PROVIDER
)
@error_decorator
def final_result_presenter(self) -> List:
...
Verbatim from the 2025-07-08 post: "each FeatureProvider is wrapped in an error-handling wrapper during the CHAOS build process. If an exception occurs, the individual feature is dropped, and the rest of the view remains unaffected. Unless developers choose to mark the feature as 'essential,' meaning its failure will affect the entire view."
The essential-feature opt-out¶
Most features on a page are additive — a user missing the "recently viewed" feature still has a usable screen. A few features are load-bearing — no search results on a search page is worse than a 500 error, because the user sees a UI with its heart ripped out.
The decorator defaults to drop-on-failure; developers
explicitly set IS_ESSENTIAL_PROVIDER = True on providers
whose absence would render the view nonsensical. This inverts
the usual default of any exception fails the request and
makes the safer-for-most-features path the easy one.
Telemetry is load-bearing¶
Verbatim (2025-07-08): "we record details such as the feature name, ownership info, exception specifics, and additional request context. This logging facilitates the monitoring of issues, the generation of alerts, and the automatic notification of the responsible team when problems reach a specified threshold."
Without telemetry this pattern silently hides bugs. The design compensates by:
- Tagging every log with feature name + owner — routes alerts to the team that can fix it.
- Including request context — allows reproduction.
- Threshold-based alerting — a single dropped feature on one request is fine; the same feature dropping on 10% of requests is a page-quality incident.
Trade-offs¶
- Silent degradation. Users may see a page that's missing a feature and not know; the system doesn't tell them. Acceptable because the feature is additive, but it does mean UX-facing monitoring must catch what the error logs catch.
- Essential-flag discipline. If every feature is marked essential, you lose the isolation; if none are, broken primary features render empty pages. Teams must decide per feature.
- Wrapper depth. The decorator must wrap the right
methods. Wrapping only the final
result_presentercan miss exceptions inload_dataorresolve; the full lifecycle needs wrapped stages (see patterns/feature-provider-lifecycle). - State left behind. A feature that throws in
resolve()may leave its state half-initialised. Other features or subsequent lifecycle hooks that read that state need to handle the empty-result case.
Related patterns¶
- patterns/feature-provider-lifecycle — the multi-stage contract this wrapper is applied to.
- concepts/blast-radius — the general principle; this is the request-scoped, feature-granular implementation.
- Netflix Hystrix / resilience4j circuit breaker — same idea at the network-call layer; this pattern applies it at the request-composition layer.
Seen in¶
- sources/2025-07-08-yelp-exploring-chaos-building-a-backend-for-server-driven-ui — Yelp's CHAOS framework; first wiki instance. Direct pseudo-code disclosure in the post.