Mark a Flow as Failed

Manually flag an HTTP or queue flow as failed when no exception was raised or auto-detected.

Overview

Use hud_sdk.set_failure() to explicitly mark the current execution (flow) as failed even when no exception occurred and Hud did not auto-detect a problem.

Marking these failures is what lets Hud treat them like any auto-detected failure. Use it so that:

  • Your error rate is accurate — the failed flow is counted, so error-rate metrics reflect reality instead of hiding gracefully-handled failures.
  • Alerts fire — Endpoint Error and Post-Deploy Error rules pick up the failure and can alert on it.
  • Forensics are collected — Hud captures forensics for the failed execution so you can debug it later.

This is useful for business-rule failures, invalid input you handle gracefully, soft-denies, or any condition you consider a failure.

When to Use

Hud automatically detects failures from unhandled exceptions and 5xx responses. But many services handle errors gracefully and never surface them as an exception or a 5xx, so Hud has no way to know the flow failed. For example:

  • An endpoint that returns 200 OK with {"status": "failed"} in the body (e.g. a declined payment).
  • An endpoint that returns 400 / 422 with a validation error instead of raising.
  • A queue consumer that swallows a bad message and logs it instead of raising.
  • Any business-rule or policy failure — missing input, soft-deny, or a disabled feature.

In these cases, call set_failure() so the failure is recorded and surfaced in Hud.


Requirements

SDKMinimum versionSupported flow types
Python0.4.2Endpoints, Queues
⚠️

Important Notes

  • set_failure() must be called during the active handling of a request or message (an active flow). Calling it outside a flow has no effect.
  • The failure message must be low-cardinality — a short, constant, stable string (e.g. "Payment provider timeout"). Hud groups occurrences into a single issue by this exact string, so never put variable or high-cardinality data (user IDs, order IDs, timestamps, request IDs) in it — pass that in the keyword metadata instead. High-cardinality messages fragment your issues and distort the error rate.
  • One call per flow — if you call it multiple times in the same flow, the last call is the one recorded.

Example #1: HTTP Handler

from flask import Flask, request
import hud_sdk

app = Flask(__name__)

@app.route("/checkout", methods=["POST"])
def checkout():
    items = request.json.get("items")
    if not items:
        hud_sdk.set_failure("Checkout attempted with no items")
        return {"status": "failure", "reason": "no items in cart"}, 400

    payment_result = process_payment(request.json)
    if not payment_result["success"]:
        hud_sdk.set_failure(
            "Payment failed",
            reason=payment_result["reason"],
            provider=payment_result["provider"],
        )
        # Note: returns 200 — the server handled it, but Hud counts it as a failure
        return {"status": "payment_failed", "reason": payment_result["reason"]}

    return {"status": "ok"}

Example #2: Queue Consumer

import hud_sdk

def process_message(msg):
    if msg.get("type") not in ["create", "update"]:
        hud_sdk.set_failure("Unsupported message type", message_type=msg.get("type"))
        return

    # Normal handling logic here
    ...

API Reference

hud_sdk.set_failure(error: str, **metadata: str | int | float | bool) -> None
  • error — a short, stable string describing the failure. Used to group failures into issues.
  • **metadata (optional) — key-value metadata passed as keyword arguments, attached to the failure for debugging (e.g. reason="timeout"). Values can be strings, numbers, or booleans.

Best Practices

  • Keep failure messages low-cardinality. Use a small, fixed set of constant strings. "Payment provider timeout" groups well; "Payment failed for user 12345 at 2026-05-20T10:30:00" is high-cardinality and creates a new issue for every occurrence, which breaks grouping and error-rate accuracy.
  • Use metadata for variable data. Put user IDs, request IDs, and other variable values in the keyword metadata instead of the error string.
  • One call per flow. If you call set_failure() multiple times in the same flow, the last call is recorded.

Notes

  • Works with any HTTP status. The flow is marked as failed regardless of the response status code. If the flow also returns 5xx, it is counted once (not double-counted).
  • No rule configuration needed. Existing Endpoint Error and Post-Deploy Error rules automatically detect user-defined failures.

set_failure also works alongside set_context and manual flows.



Did this page help you?