After fixing the webhook issues, events were being ingested successfully
but all of them were ending up with processing_status = failed in the database.
Checked the ai-service logs and found this error repeating for every event:
the JSON object must be str, bytes or bytearray, not dict
Traced it to get_event_by_id() in backend/ai-service/app/database.py:
result["raw_data"] = json.loads(result["raw_data"])
psycopg2 already deserializes JSONB columns into Python dicts automatically,
so calling json.loads() on top of that fails immediately.
Fix:
Added a type check before parsing:
if isinstance(result["raw_data"], str):
result["raw_data"] = json.loads(result["raw_data"])
This way it only parses if the value is actually a string, and skips it
when psycopg2 has already done the work.
After this fix events move from failed → completed correctly.
After fixing the webhook issues, events were being ingested successfully
but all of them were ending up with processing_status = failed in the database.
Checked the ai-service logs and found this error repeating for every event:
the JSON object must be str, bytes or bytearray, not dict
Traced it to get_event_by_id() in backend/ai-service/app/database.py:
result["raw_data"] = json.loads(result["raw_data"])
psycopg2 already deserializes JSONB columns into Python dicts automatically,
so calling json.loads() on top of that fails immediately.
Fix:
Added a type check before parsing:
if isinstance(result["raw_data"], str):
result["raw_data"] = json.loads(result["raw_data"])
This way it only parses if the value is actually a string, and skips it
when psycopg2 has already done the work.
After this fix events move from failed → completed correctly.