{"record":{"id":"24ca020706b29842","repo":"lfnovo/open-notebook","slug":"str-e-24ca02","errorCode":null,"errorMessage":"{str(e)}","messagePattern":"\\{str\\(e\\)\\}","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"api/routers/search.py","lineNumber":56,"sourceCode":"                minimum_score=search_request.minimum_score,\n            )\n        else:\n            # Text search\n            results = await text_search(\n                keyword=search_request.query,\n                results=search_request.limit,\n                source=search_request.search_sources,\n                note=search_request.search_notes,\n            )\n\n        return SearchResponse(\n            results=results or [],\n            total_count=len(results) if results else 0,\n            search_type=search_request.type,\n        )\n\n    except InvalidInputError as e:\n        raise HTTPException(status_code=400, detail=str(e))\n    except DatabaseOperationError as e:\n        logger.error(f\"Database error during search: {str(e)}\")\n        raise HTTPException(status_code=500, detail=f\"Search failed: {str(e)}\")\n    except HTTPException:\n        raise\n    except OpenNotebookError:\n        raise\n    except Exception as e:\n        logger.error(f\"Unexpected error during search: {str(e)}\")\n        raise HTTPException(status_code=500, detail=f\"Search failed: {str(e)}\")\n\n\nasync def stream_ask_response(\n    question: str, strategy_model: Model, answer_model: Model, final_answer_model: Model\n) -> AsyncGenerator[str, None]:\n    \"\"\"Stream the ask response as Server-Sent Events.\"\"\"\n    try:\n        final_answer = None","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/lfnovo/open-notebook/blob/a7de90d38aaf18ee85fd661854d35c11e44613e2/api/routers/search.py#L38-L74","documentation":"400 that transparently re-wraps an InvalidInputError from the search layer, passing its message through as the HTTP detail. It means the search request itself was malformed (e.g. empty/invalid query or bad search parameters).","triggerScenarios":"POST /api/search where the query string is empty, too long, or the search type/query combination fails validation inside vector_search/full_text_search.","commonSituations":"Frontend sending an empty query box value, whitespace-only queries, unsupported search type string reaching the service layer.","solutions":["Ensure the query field is non-empty and trimmed","Send a supported type ('text' or 'vector')","Check the error detail — it contains the original InvalidInputError message"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const q = query.trim();\nif (!q) throw new Error('Query required');\nif (!['text','vector'].includes(type)) throw new Error('Bad type');","typeGuard":null,"tryCatchPattern":"catch (e) { if (e.status === 400) showUserMessage(e.detail); }","preventionTips":["Trim and require non-empty query before submit","Restrict type to the supported enum client-side"],"tags":["input-validation","search","http-400"],"backgroundTag":"invalid-request-parameters","analyzedSha":"a7de90d38aaf18ee85fd661854d35c11e44613e2","analyzedAt":"2026-08-27T02:39:58.166Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}