{"record":{"id":"bae24282dd92b322","repo":"NanmiCoder/MediaCrawler","slug":"e","errorCode":null,"errorMessage":"{e}","messagePattern":"\\{e\\}","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"api/routers/data.py","lineNumber":156,"sourceCode":"                import pandas as pd\n                # Read first limit rows\n                df = pd.read_excel(full_path, nrows=limit)\n                # Get total row count (only read first column to save memory)\n                df_count = pd.read_excel(full_path, usecols=[0])\n                total = len(df_count)\n                # Convert to list of dictionaries, handle NaN values\n                rows = df.where(pd.notnull(df), None).to_dict(orient='records')\n                return {\n                    \"data\": rows,\n                    \"total\": total,\n                    \"columns\": list(df.columns)\n                }\n            else:\n                raise HTTPException(status_code=400, detail=\"Unsupported file type for preview\")\n        except json.JSONDecodeError:\n            raise HTTPException(status_code=400, detail=\"Invalid JSON file\")\n        except Exception as e:\n            raise HTTPException(status_code=500, detail=str(e))\n    else:\n        # Return file download\n        return FileResponse(\n            path=full_path,\n            filename=full_path.name,\n            media_type=\"application/octet-stream\"\n        )\n\n\n@router.get(\"/download/{file_path:path}\")\nasync def download_file(file_path: str):\n    \"\"\"Download file\"\"\"\n    full_path = DATA_DIR / file_path\n\n    if not full_path.exists():\n        raise HTTPException(status_code=404, detail=\"File not found\")\n\n    if not full_path.is_file():","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/NanmiCoder/MediaCrawler/blob/d6f7c5bb906b6dac40ddf343ef9e26438a3de092/api/routers/data.py#L138-L174","documentation":"HTTP 500 with detail=str(e) — the catch-all handler in the preview branch of GET /api/data/files. Any exception other than JSONDecodeError from the csv/json/pandas readers lands here: pandas parse errors on corrupt xlsx/csv, OSError on permission or encoding failures, or MemoryError on huge files. Because the raw exception string is echoed to the client, the response can leak server-side paths and library internals.","triggerScenarios":"Previewing a corrupt .xlsx that pandas cannot parse; permission-denied on the data file for the API process; a csv with mixed encoding raising UnicodeDecodeError; read_excel blowing up on a huge or non-spreadsheet file renamed to .xlsx.","commonSituations":"Excel files saved in legacy .xls format but renamed to .xlsx; files locked by another process on Windows; disk/permission misconfiguration of DATA_DIR; concurrent write by the crawler producing a partially-flushed file.","solutions":["Download the file (preview=false) and open it locally to see the real parsing problem.","Check API-process read permissions on DATA_DIR and the specific file.","Re-save the Excel/CSV from its source application in a supported, well-formed format.","As the API maintainer: log the full traceback server-side and return a generic 500 detail instead of str(e)."],"exampleFix":"# before\nexcept Exception as e:\n    raise HTTPException(status_code=500, detail=str(e))\n\n# after\nexcept Exception as e:\n    logger.exception(\"file preview failed\")\n    raise HTTPException(status_code=500, detail=\"Failed to preview file\")","handlingStrategy":"fallback","validationCode":"const size = (await fetch(`/api/data/files/${path}?preview=false`)).headers.get('content-length');\nif (Number(size) > 10_000_000) { /* skip preview, download instead */ }","typeGuard":null,"tryCatchPattern":"try { preview = await getPreview(path); } catch (e) { if (e.status === 500) { preview = await downloadRaw(path); /* fall back to raw bytes */ } }","preventionTips":["Fall back to preview=false (raw download) when preview 500s","Verify the file opens in a local reader before retrying preview","If you maintain the API, never return str(e) to clients — log it server-side instead"],"tags":["api","http-500","pandas","error-handling","information-disclosure"],"backgroundTag":null,"analyzedSha":"d6f7c5bb906b6dac40ddf343ef9e26438a3de092","analyzedAt":"2026-08-15T01:39:07.505Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}