fix: use correct schema name in webhook outbox callback to prevent silent transaction rollback (#499)

The retain outbox callback was passing context.tenant_id (raw UUID like
0f3ad4ec-8b88-...) instead of the PostgreSQL schema name (tenant_0f3ad4ec_...).
This caused the webhook manager to query a non-existent schema, triggering a
PostgreSQL error that silently aborted the entire retain transaction — rolling
back all inserted memory data with no clear indication of data loss.

Fixed both the async worker path (memory_engine.py) and sync HTTP path (http.py)
to use _current_schema.get() which holds the correct tenant-prefixed schema name.

Also changed fire_event_with_conn to re-raise exceptions instead of swallowing
them, since errors inside a caller's transaction poison it irreversibly.
This commit is contained in:
Chris Bartholomew 2026-03-05 11:07:48 -05:00 committed by GitHub
parent d425e93cb4
commit 75b95106ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 8 additions and 4 deletions

View file

@ -72,7 +72,7 @@ def FieldWithDefault(default_factory: Callable, **kwargs) -> Any:
from hindsight_api.config import get_config from hindsight_api.config import get_config
from hindsight_api.engine.db_utils import acquire_with_retry from hindsight_api.engine.db_utils import acquire_with_retry
from hindsight_api.engine.memory_engine import Budget, _get_tiktoken_encoding, fq_table from hindsight_api.engine.memory_engine import Budget, _current_schema, _get_tiktoken_encoding, fq_table
from hindsight_api.engine.reflect.observations import Observation from hindsight_api.engine.reflect.observations import Observation
from hindsight_api.engine.response_models import VALID_RECALL_FACT_TYPES, MemoryFact, TokenUsage from hindsight_api.engine.response_models import VALID_RECALL_FACT_TYPES, MemoryFact, TokenUsage
from hindsight_api.engine.search.tags import TagsMatch from hindsight_api.engine.search.tags import TagsMatch
@ -4280,7 +4280,7 @@ def _register_routes(app: FastAPI):
bank_id=bank_id, bank_id=bank_id,
contents=contents, contents=contents,
operation_id=None, operation_id=None,
schema=request_context.tenant_id, schema=_current_schema.get(),
), ),
) )

View file

@ -594,7 +594,7 @@ class MemoryEngine(MemoryEngineInterface):
bank_id=bank_id, bank_id=bank_id,
contents=contents, contents=contents,
operation_id=operation_id, operation_id=operation_id,
schema=context.tenant_id, schema=_current_schema.get(),
), ),
) )

View file

@ -235,4 +235,8 @@ class WebhookManager:
) )
except Exception as e: except Exception as e:
logger.error(f"Failed to queue webhook deliveries (in-transaction) for event {event.event}: {e}") logger.error(
f"Failed to queue webhook deliveries (in-transaction) for event {event.event}: {e}. "
"CRITICAL: The enclosing database transaction is now aborted and will roll back all changes."
)
raise