odysseus-dev/odysseus · error · HTTPException

Webhook not found

Error message

Webhook not found

What it means

HTTP 404 from POST /webhooks/{webhook_id}/test. The route looks the webhook up by its 8-character short id in the Webhook table; no row matches, so the test delivery is refused. Distinct from delivery failures — the webhook record itself does not exist.

Source

Thrown at routes/webhook/webhook_routes.py:148

                url=url,
                secret=encrypted_secret,
                events=events,
                is_active=True,
            ))
            db.commit()
        finally:
            db.close()

        return {"id": webhook_id, "name": name}

    @router.post("/webhooks/{webhook_id}/test")
    async def test_webhook(request: Request, webhook_id: str):
        _require_admin(request)
        db = SessionLocal()
        try:
            wh = db.query(Webhook).filter(Webhook.id == webhook_id).first()
            if not wh:
                raise HTTPException(404, "Webhook not found")
            url, secret = wh.url, wh.secret
        finally:
            db.close()

        await webhook_manager.deliver_test(webhook_id, url, secret)
        return {"status": "sent"}

    @router.patch("/webhooks/{webhook_id}")
    def toggle_webhook(request: Request, webhook_id: str):
        _require_admin(request)
        db = SessionLocal()
        try:
            wh = db.query(Webhook).filter(Webhook.id == webhook_id).first()
            if not wh:
                raise HTTPException(404, "Webhook not found")
            wh.is_active = not wh.is_active
            db.commit()
            return {"id": webhook_id, "is_active": wh.is_active}

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Re-fetch the webhook list (GET /webhooks) and use a current id
  2. If the webhook was deleted, recreate it first, then test
  3. Confirm you are pointed at the same server/database the webhook was created on
Defensive patterns

Strategy: validation

Validate before calling

hooks = requests.get(f"{base}/api/webhooks", headers=h).json()
ids = {w["id"] for w in hooks}
assert webhook_id in ids, f"{webhook_id} no longer exists; refresh list"

Try / catch

if resp.status_code == 404:
    # webhook record gone: refresh list, recreate, or drop it from UI

Prevention

When it happens

Trigger: Calling the test endpoint with an id that was deleted, a typo'd id, an id from a different database/environment, or before the creating transaction of a brand-new webhook is visible to this SessionLocal.

Common situations: UI still showing a stale webhook list after a delete; copy-paste of the wrong 8-char id (they are short and collision-prone); testing against a fresh dev database that was re-seeded while the client held old ids.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/8b1ade30af23af13. Report an issue: GitHub.