ZhuLinsen/daily_stock_analysis · error · HTTPException
invalid_request
invalid_request
Error message
stock_code 不能为空
What it means
This is a 400 invalid_request raised by DELETE /api/v1/history/by-code/{stock_code} when the stock_code path parameter normalizes to nothing. The endpoint calls HistoryService._history_code_filter_candidates(stock_code), which strips whitespace and returns [] only when the input is empty or whitespace-only (src/services/history_service.py:99-102). Any non-blank string, even a malformed code, produces at least one candidate, so this error fires almost exclusively on blank input.
Source
Thrown at api/v1/endpoints/history.py:318
"/by-code/{stock_code}",
response_model=DeleteHistoryResponse,
responses={
200: {"description": "删除成功"},
400: {"description": "股票代码不能为空", "model": ErrorResponse},
404: {"description": "未找到记录", "model": ErrorResponse},
500: {"description": "服务器错误", "model": ErrorResponse},
},
summary="按股票代码删除历史分析记录",
description="删除指定股票代码的所有分析历史记录(支持代码变体归一化匹配)",
)
def delete_history_by_code(
stock_code: str,
db_manager: DatabaseManager = Depends(get_database_manager),
) -> DeleteHistoryResponse:
try:
candidates = HistoryService._history_code_filter_candidates(stock_code)
if not candidates:
raise HTTPException(
status_code=400,
detail={"error": "invalid_request", "message": "stock_code 不能为空"},
)
deleted = 0
while True:
records, _ = db_manager.get_analysis_history_paginated(
code=candidates,
limit=_DELETE_BY_CODE_BATCH_SIZE,
)
record_ids = [r.id for r in records if r.id is not None]
if not record_ids:
break
batch_deleted = db_manager.delete_analysis_history_records(record_ids)
if batch_deleted == 0:
raise RuntimeError("history deletion made no progress")
deleted += batch_deletedView on GitHub (pinned to 5159bd72e8)
Solutions
- Ensure the client has a non-empty stock code before issuing the request (guard with if (!stockCode?.trim()) ...).
- Verify the exact route: the code must be supplied as the stock_code path segment, e.g. DELETE /api/v1/history/by-code/600519.
- If the code comes from user input, trim it and reject blank values in the UI/script before calling the API.
- If you still get 400 with a visible code, confirm no proxy is stripping the path segment.
Example fix
// before
const res = await fetch(`/api/v1/history/by-code/${code}`, { method: 'DELETE' });
// after
const trimmed = (code ?? '').trim();
if (!trimmed) throw new Error('stock_code is required');
const res = await fetch(`/api/v1/history/by-code/${encodeURIComponent(trimmed)}`, { method: 'DELETE' }); Defensive patterns
Strategy: validation
Validate before calling
const code = String(stockCode ?? '').trim();
if (!code) {
throw new Error('stock_code must be a non-empty stock code');
}
await fetch(`/api/v1/history/by-code/${encodeURIComponent(code)}`, { method: 'DELETE' }); Type guard
const isNonEmptyStockCode = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0;
Try / catch
try { const res = await delByCode(code); if (res.status === 400) handleInvalidRequest(); } catch (e) { /* network only */ } Prevention
- Trim and require non-empty stock codes before building the delete URL.
- URL-encode path parameters to avoid whitespace/encoding edge cases.
- Never template a URL from possibly-undefined state; default to disabled submit buttons.
When it happens
Trigger: Calling DELETE /history/by-code/ (empty path segment), /history/by-code/%20, or /history/by-code/%00-style whitespace-only values. A URL-encoded space or a client that builds the path from an unset/None stock variable (rendered as empty string) also triggers it.
Common situations: Frontend builds the delete URL from a state field that has not been initialized yet (empty string template interpolation); automated scripts iterating a list where some entries are empty strings; trailing-slash routing that maps to an empty path parameter
Related errors
- invalid_params
- validation_error
- invalid_stock_code
- invalid_import_file
- [AlphaVantage] {stock_code} is not a US stock
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/17346e3694b4f1fa.
Report an issue: GitHub.