Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""add error message column in collections table
Revision ID: 5a59c6c29a82
Revises: e9dd35eff62c
Create Date: 2025-08-11 15:40:40.127161
"""
from alembic import op
import sqlalchemy as sa
import sqlmodel.sql.sqltypes


# revision identifiers, used by Alembic.
revision = "5a59c6c29a82"
down_revision = "e9dd35eff62c"
branch_labels = None
depends_on = None


def upgrade():
op.add_column(
"collection",
sa.Column("error_message", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
)


def downgrade():
op.drop_column("collection", "error_message")
34 changes: 33 additions & 1 deletion backend/app/api/routes/collections.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import inspect
import logging
import time
import json
import ast
import re
from uuid import UUID, uuid4
from typing import Any, List, Optional
from dataclasses import dataclass, field, fields, asdict, replace
Expand All @@ -13,6 +16,7 @@

from app.api.deps import CurrentUser, SessionDep, CurrentUserOrgProject
from app.core.cloud import AmazonCloudStorage
from app.api.routes.responses import handle_openai_error
from app.core.util import now, post_callback
from app.crud import (
DocumentCrud,
Expand All @@ -28,6 +32,32 @@
router = APIRouter(prefix="/collections", tags=["collections"])


def extract_error_message(err: Exception) -> str:
err_str = str(err).strip()

body = re.sub(r"^Error code:\s*\d+\s*-\s*", "", err_str)
message = None
try:
payload = json.loads(body)
if isinstance(payload, dict):
message = payload.get("error", {}).get("message")
except Exception:
pass

if message is None:
try:
payload = ast.literal_eval(body)
if isinstance(payload, dict):
message = payload.get("error", {}).get("message")
except Exception:
pass

if not message:
message = body

return message.strip()[:1000]


@dataclass
class ResponsePayload:
status: str
Expand Down Expand Up @@ -246,6 +276,9 @@ def do_create_collection(
collection = collection_crud.read_one(UUID(payload.key))
collection.status = CollectionStatus.failed
collection.updated_at = now()
message = extract_error_message(err)
collection.error_message = message

collection_crud._update(collection)
except Exception as suberr:
logger.warning(
Expand Down Expand Up @@ -283,7 +316,6 @@ def create_collection(
collection_crud = CollectionCrud(session, current_user.id)
collection_crud.create(collection)

# 2. Launch background task
background_tasks.add_task(
do_create_collection, session, current_user, request, payload, client
)
Expand Down
10 changes: 6 additions & 4 deletions backend/app/crud/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,15 @@ def read_each(self, doc_ids: List[UUID]):
)
results = self.session.exec(statement).all()

(m, n) = map(len, (results, doc_ids))
if m != n:
(retrieved_count, requested_count) = map(len, (results, doc_ids))
if retrieved_count != requested_count:
try:
raise ValueError(f"Requested {n} retrieved {m}")
raise ValueError(
f"Requested atleast {requested_count} document retrieved {retrieved_count}"
)
except ValueError as err:
logger.error(
f"[DocumentCrud.read_each] Mismatch in retrieved documents | {{'owner_id': {self.owner_id}, 'requested_count': {n}, 'retrieved_count': {m}}}",
f"[DocumentCrud.read_each] Mismatch in retrieved documents | {{'owner_id': {self.owner_id}, 'requested_count': {requested_count}, 'retrieved_count': {retrieved_count}}}",
exc_info=True,
)
raise
Expand Down
1 change: 1 addition & 0 deletions backend/app/models/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class Collection(SQLModel, table=True):
llm_service_name: Optional[str] = Field(default=None, nullable=True)

status: CollectionStatus = Field(default=CollectionStatus.processing)
error_message: Optional[str] = Field(default=None, nullable=True)

created_at: datetime = Field(default_factory=now)
updated_at: datetime = Field(default_factory=now)
Expand Down