ZhuLinsen/daily_stock_analysis · error · ValueError

文件超过 {MAX_FILE_BYTES // (1024 * 1024)}MB 限制

Error message

文件超过 {MAX_FILE_BYTES // (1024 * 1024)}MB 限制

What it means

Guard in parse_import_from_bytes: uploaded file exceeds MAX_FILE_BYTES (2MB). Enforced before any format sniffing to bound parser memory use.

Source

Thrown at src/services/import_parser.py:143

    return result


def parse_import_from_bytes(data: bytes, filename: Optional[str] = None) -> List[Tuple[Optional[str], Optional[str], str]]:
    """
    Parse file bytes (CSV/Excel) into items.

    Args:
        data: File content bytes.
        filename: Optional filename for format detection (e.g. "a.csv", "b.xlsx").

    Returns:
        List of (code, name, confidence); code may be None if resolution failed.

    Raises:
        ValueError: On parse error or unsupported format.
    """
    if len(data) > MAX_FILE_BYTES:
        raise ValueError(f"文件超过 {MAX_FILE_BYTES // (1024 * 1024)}MB 限制")

    ext = ""
    if filename:
        ext = "." + filename.rsplit(".", 1)[-1].lower() if "." in filename else ""
    logger.debug(f"[ImportParser] 开始解析文件: filename={filename or '-'}, ext={ext or '-'}, bytes={len(data)}")

    looks_like_zip = len(data) >= 4 and data[:4] == b"PK\x03\x04"

    # Excel: .xlsx (or zip magic)
    if ext == ".xlsx" or looks_like_zip:
        try:
            # Use header=None to avoid silently consuming the first data row as column names
            # when the sheet has no header row. We detect headers the same way as the CSV path.
            df = pd.read_excel(io.BytesIO(data), sheet_name=0, engine="openpyxl", header=None, dtype=str)
            if df is None or df.empty:
                return []
            df = df.fillna("")
            first_row = [str(x).strip().lower() for x in df.iloc[0].tolist()]

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Trim the file to only the needed columns (code, name) before import
  2. For CSV, strip headers/extra columns; for xlsx, save as CSV of just the code column
  3. Compress workflow: paste text instead (parse_import_from_text allows 100KB) or split into batches

Example fix

# before
items = parse_import_from_bytes(open('portfolio.xlsx','rb').read(), 'portfolio.xlsx')  # >2MB
# after: extract just the code column to CSV first
items = parse_import_from_bytes(csv_only_bytes, 'portfolio.csv')
Defensive patterns

Strategy: validation

Validate before calling

from src.services.import_parser import MAX_FILE_BYTES
if len(data) > MAX_FILE_BYTES:
    raise ValueError(f'文件过大,请精简到 {MAX_FILE_BYTES // (1024*1024)}MB 以内(仅保留代码/名称列)')

Type guard

def within_file_limit(b: bytes) -> bool:
    return len(b) <= 2 * 1024 * 1024

Prevention

When it happens

Trigger: Uploading a CSV/XLSX import file larger than 2MB; exporting a full watchlist with names and extra columns.

Common situations: Large broker exports; xlsx with embedded formatting/images inflating size; pasting whole portfolio history instead of the code column.

Related errors


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