{"record":{"id":"a00b97f5098eb9b3","repo":"Zie619/n8n-workflows","slug":"trend-analysis-error-str-e","errorCode":null,"errorMessage":"Trend analysis error: {str(e)}","messagePattern":"Trend analysis error: (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"src/analytics_engine.py","lineNumber":375,"sourceCode":"\n        return AnalyticsResponse(\n            overview=analytics_data[\"overview\"],\n            trends=trends,\n            patterns=analytics_data[\"patterns\"],\n            recommendations=analytics_data[\"recommendations\"],\n            generated_at=analytics_data[\"generated_at\"],\n        )\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=f\"Analytics error: {str(e)}\")\n\n\n@analytics_app.get(\"/analytics/trends\")\nasync def get_trend_analysis(days: int = Query(30, ge=1, le=365)):\n    \"\"\"Get trend analysis for specified period.\"\"\"\n    try:\n        return analytics_engine.get_trend_analysis(days)\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=f\"Trend analysis error: {str(e)}\")\n\n\n@analytics_app.get(\"/analytics/insights\")\nasync def get_usage_insights():\n    \"\"\"Get usage insights and patterns.\"\"\"\n    try:\n        return analytics_engine.get_usage_insights()\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=f\"Insights error: {str(e)}\")\n\n\n@analytics_app.get(\"/analytics/dashboard\")\nasync def get_analytics_dashboard():\n    \"\"\"Get analytics dashboard HTML.\"\"\"\n    html_content = \"\"\"\n    <!DOCTYPE html>\n    <html lang=\"en\">\n    <head>","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/src/analytics_engine.py#L357-L393","documentation":"A generic 500 from GET /analytics/trends?days=N. The handler delegates straight to analytics_engine.get_trend_analysis(days); any exception is re-raised as 500 with the original message. The days parameter is already validated by FastAPI (1..365), so failures come from the engine's date bucketing or data access, not from input validation.","triggerScenarios":"Calling /analytics/trends when the underlying events table is missing/locked, or when trend bucketing divides by zero / parses bad timestamps on empty or malformed event rows. days=1 edge cases with sparse data can also expose math errors in per-day aggregation.","commonSituations":"Analytics DB not yet created on a new deployment; events table exists but rows have NULL timestamps from an older writer; concurrent write during read causing 'database is locked'.","solutions":["Check the appended str(e) — 'no such table' means init the DB; 'database is locked' means serialize writers or enable WAL.","Initialize the analytics storage and record at least a few events, then retry.","Try a default days=30 call first to rule out edge-value bugs with days=1.","If timestamps are the issue, backfill/repair NULL created_at values in the events table."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"def valid_days(days: int) -> bool:\n    return isinstance(days, int) and 1 <= days <= 365","typeGuard":null,"tryCatchPattern":"try:\n    trends = client.get(\"/analytics/trends\", params={\"days\": days}).json()\nexcept HTTPError as e:\n    if e.response.status_code == 500:\n        trends = {\"trends\": [], \"period_days\": days}  # neutral empty result\n    else:\n        raise","preventionTips":["Always pass days within 1..365; other values are rejected by validation (422), not this handler.","Default charts to a 'no trend data' state when the endpoint errors.","Record at least a few usage events in test environments before asserting on trends."],"tags":["http-500","analytics","trends","sqlite","fastapi"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}