ZhuLinsen/daily_stock_analysis · warning · HTTPException

invalid_json

invalid_json

Error message

JSON 解析失败: {e}

What it means

Raised by POST /api/v1/stocks/parse-import when the request declares application/json but the body cannot be parsed by request.json(). Any JSONDecodeError-style failure is converted to HTTP 400 with error code invalid_json and the parser's message embedded; the raw parse error is also logged as a warning.

Solutions

  1. Validate the body with JSON.parse (JS) or json.loads (Python) before sending, and log the exact payload on failure.
  2. Quote keys and use double quotes throughout: {"text": "..."}.
  3. Strip any BOM and ensure Content-Type matches the actual body format.

Example fix

# before
curl -X POST .../parse-import -H 'Content-Type: application/json' -d '{text: "600519"}'

# after
curl -X POST .../parse-import -H 'Content-Type: application/json' -d '{"text": "600519"}'
Defensive patterns

Strategy: validation

Validate before calling

let payload;
try { payload = JSON.parse(rawBodyText); } catch (e) {
  showError('JSON 格式错误: ' + e.message); return;
}
await fetch(url, {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(payload)});

Type guard

function isJsonObject(v: unknown): v is Record<string, unknown> {
  if (typeof v !== 'object' || v === null || Array.isArray(v)) return false;
  try { JSON.parse(JSON.stringify(v)); return true; } catch { return false; }
}

Prevention

When it happens

Trigger: Sending text/plain or form-encoded data with a JSON content-type header; a body with trailing commas, single quotes, unescaped newlines, or a BOM prefix; an empty body with Content-Type: application/json; truncated JSON from a proxy.

Common situations: Hand-built curl -d '{text: "..."}' (unquoted key, single quotes); pasting JSON containing literal newlines inside strings; Windows editors adding a UTF-8 BOM; JS sending a stringified object twice (JSON.stringify(JSON.stringify(x))).

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/c4b498e3bdaeba54. Report an issue: GitHub.

Appendix: source

Thrown at api/v1/endpoints/stocks.py:224

    summary="解析 CSV/Excel/剪贴板",
    description="上传 CSV/Excel 文件或粘贴文本,自动解析股票代码。文件上限 2MB,文本上限 100KB。",
)
async def parse_import(request: Request) -> ExtractFromImageResponse:
    """
    解析 CSV/Excel 文件或剪贴板文本。

    - multipart/form-data + file: 上传文件
    - application/json + {"text": "..."}: 粘贴文本
    - 优先使用 file,若同时提供则忽略 text
    """
    content_type = (request.headers.get("content-type") or "").lower()

    if "application/json" in content_type:
        try:
            body = await request.json()
        except Exception as e:
            logger.warning("[parse_import] JSON parse failed: %s", e)
            raise HTTPException(
                status_code=400,
                detail={"error": "invalid_json", "message": f"JSON 解析失败: {e}"},
            )
        text = body.get("text") if isinstance(body, dict) else None
        if not text or not isinstance(text, str):
            raise HTTPException(
                status_code=400,
                detail={"error": "bad_request", "message": "未提供 text,请使用 {\"text\": \"...\"}"},
            )
        try:
            items = parse_import_from_text(text)
        except ValueError as e:
            text_bytes = len(text.encode("utf-8"))
            logger.warning(
                "[parse_import] parse_import_from_text failed: text_bytes=%d, error=%s",
                text_bytes,
                e,
            )

View on GitHub (pinned to 5159bd72e8)