ZhuLinsen/daily_stock_analysis · error · ValueError

Image too large (max {MAX_SIZE_BYTES // (1024 * 1024)}MB)

Error message

Image too large (max {MAX_SIZE_BYTES // (1024 * 1024)}MB)

What it means

Guard in extract_stock_codes_from_image: len(image_bytes) exceeds MAX_SIZE_BYTES (5MB). Checked before magic-byte verification and base64 encoding, because base64 inflates payload ~33% and vision APIs have request-size limits.

Source

Thrown at src/services/image_stock_extractor.py:373

    Args:
        image_bytes: 原始图片字节
        mime_type: MIME 类型(如 image/jpeg, image/png)

    Returns:
        (items, raw_text) - items 为 [(code, name?, confidence), ...],raw_text 为原始 LLM 响应。

    Raises:
        ValueError: 图片无效、未配置 Vision API 或提取失败时。
    """
    mime_type = (mime_type or "image/jpeg").strip().lower().split(";")[0].strip()
    if mime_type not in ALLOWED_MIME:
        raise ValueError(f"不支持的图片类型: {mime_type}。允许: {list(ALLOWED_MIME)}")

    if not image_bytes:
        raise ValueError("图片内容为空")

    if len(image_bytes) > MAX_SIZE_BYTES:
        raise ValueError(f"Image too large (max {MAX_SIZE_BYTES // (1024 * 1024)}MB)")

    _verify_image_magic_bytes(image_bytes, mime_type)

    image_b64 = base64.b64encode(image_bytes).decode("ascii")
    model = _resolve_vision_model()
    keys = _get_api_keys_for_model(model, get_config())

    last_error: Optional[Exception] = None
    for attempt in range(3):
        try:
            key = random.choice(keys) if keys else None
            raw = _call_litellm_vision(image_b64, mime_type, api_key=key)
            logger.debug("[ImageExtractor] raw LLM response:\n%s", raw)
            items = _parse_items_from_text(raw)
            logger.info(
                f"[ImageExtractor] {model} 提取 {len(items)} 个: "
                f"{[(i[0], i[1]) for i in items[:5]]}{'...' if len(items) > 5 else ''}"
            )

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Compress/resize client-side before upload (canvas resize or quality reduction to JPEG)
  2. If high fidelity needed, downscale to ~2000px and re-encode as JPEG — vision models don't need full resolution
  3. Enforce a 5MB limit in the upload UI so the error never reaches the backend

Example fix

# before
items, raw = extract_stock_codes_from_image(open('huge.png','rb').read(), 'image/png')  # >5MB
# after: downscale + re-encode
from PIL import Image
im = Image.open('huge.png'); im.thumbnail((2000, 2000))
buf = io.BytesIO(); im.convert('RGB').save(buf, 'JPEG', quality=85)
items, raw = extract_stock_codes_from_image(buf.getvalue(), 'image/jpeg')
Defensive patterns

Strategy: validation

Validate before calling

from src.services.image_stock_extractor import MAX_SIZE_BYTES
if len(image_bytes) > MAX_SIZE_BYTES:
    image_bytes, mime = downscale_and_reencode(image_bytes, max_px=2000)

Type guard

def within_image_limit(b: bytes) -> bool:
    return len(b) <= 5 * 1024 * 1024

Prevention

When it happens

Trigger: Uploading a photo/screenshot larger than 5MB (common with modern phone photos and high-res screenshots).

Common situations: Direct phone photo uploads; PNG screenshots of multi-monitor setups; no client-side size limit enforced.

Related errors


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