Skip to content

Feature/centralized error handling#182

Open
aneesafatima wants to merge 4 commits intoAOSSIE-Org:mainfrom
aneesafatima:feature/centralized-error-handling
Open

Feature/centralized error handling#182
aneesafatima wants to merge 4 commits intoAOSSIE-Org:mainfrom
aneesafatima:feature/centralized-error-handling

Conversation

@aneesafatima
Copy link
Contributor

@aneesafatima aneesafatima commented Jan 27, 2026

Closes #171

📝 Description

This PR implements a comprehensive error handling system for the Flask application, introducing environment-based error responses, custom error classes, and unified error handling across all routes. The implementation includes significant bug fixes discovered during testing and establishes consistent patterns for error management throughout the codebase.

Key Improvements:

  • Environment-aware error handling: Development mode provides detailed error information for debugging, while production mode returns user-friendly messages
  • Custom error classes: Centralized error handling with MissingFieldError and NotFoundError classes
  • Database error management: Decorator-based approach to handle SQLite errors consistently
  • Input validation: Comprehensive validation utilities for blood pressure, medicine, and weight data
  • Bug fixes: Resolved multiple critical issues including route conflicts, missing validations, and inconsistent HTTP methods

🔧 Changes Made

1. Environment Configuration & CLI Support

  • Added argparse integration for command-line environment selection
    • Usage: python app.py --env development or python app.py --env production
    • Stored environment in app.config['ENV'] for application-wide access
  • Dynamic port configuration based on environment:
    • Development: Uses DEV_PORT env var (defaults to 5000)
    • Production: Uses PROD_PORT env var (defaults to 8000)

2. Custom Error Classes

Created custom exception classes in the error handling module:

class MissingFieldError(Exception):
    """Exception raised when required fields are missing"""
    status_code = 400
    - Accepts list of missing field names
    - Returns field-specific errors in development mode
    - Returns generic message in production mode

class NotFoundError(Exception):
    """Exception raised when a resource is not found"""
    status_code = 404
    - Accepts resource type and optional resource ID
    - Provides detailed info in development mode

3. Global Error Handlers

Registered five comprehensive error handlers on the Flask app instance:

  • MissingFieldError handler: Returns missing field details in dev, generic message in prod
  • NotFoundError handler: Returns resource-specific 404 responses
  • BadRequest handler: Catches malformed JSON and invalid requests (triggered by request.get_json())
  • UnsupportedMediaType handler: Returns 415 when Content-Type is not application/json
  • Exception handler: Catches all unhandled exceptions with environment-aware responses

4. Database Error Handling

  • Created @handle_db_errors decorator to wrap all routes performing database operations
  • Handles OperationalError and DatabaseError from SQLite3
  • Returns appropriate status codes (500) with environment-aware error messages
  • Discovered and fixed: Multiple routes had no database error handling at all
  • Removed redundant close_db() calls: Application already uses @app.teardown_appcontext for cleanup

5. Request Handling Improvements

  • Replaced request.json with request.get_json() throughout the application
    • request.get_json() automatically raises BadRequest for malformed JSON
    • request.json silently accepts invalid data, leading to runtime errors
    • This change ensures early validation and proper error responses

6. Input Validation Utilities

Created utils.py with validation functions:

  • validate_bp_data(data): Validates blood pressure entries

    • week_number: Must be positive integer
    • systolic: Must be integer between 50-300
    • diastolic: Must be integer between 30-200
  • validate_medicine_data(data): Validates medicine entries

    • week_number: Validates using validate_week_number()
    • name: Must be non-empty string
    • dose: Must be non-empty string
  • validate_week_number(week): Ensures week is integer between 1-52

  • validate_weight_value(weight): Ensures weight is positive number up to 1000kg

7. HTTP Method Corrections

  • Changed PUT to PATCH for update operations across multiple routes
    • Routes were using old values for unprovided fields (PATCH behavior)
    • Updated both backend routes and corresponding frontend calls
    • Ensures semantic correctness and REST compliance

8. Route Conflict Resolution

Fixed duplicate route patterns that caused Flask routing conflicts:

Weight Routes:

  • Before: /weight/<int:id> used for both ideal weight and week-based weight
  • After:
    • /weight/<int:id> for ideal weight operations
    • /weight/week/<int:id> for week-based weight operations

Medicine Routes:

  • Before: /medicine/<int:id> caused similar conflicts
  • After: Separated routes with explicit path segments

9. Critical Bug Fixes

Bug #1: Missing Validation in Create Operations

  • Issue: Blood pressure and medicine CREATE routes had no validation, but UPDATE routes did
  • Impact: Users could create invalid data that would fail validation on update
  • Fix: Applied validation utilities to both CREATE and UPDATE operations

Bug #2: Incomplete SQL Parameters

  • Issue: Several routes had SQL queries with missing or incorrect parameter bindings
  • Impact: Potential SQL errors or use of stale/default data
  • Fix: Ensured all parameterized queries receive correct values from request data

Bug #3: Incorrect Default Values in Updates

  • Issue: Update operations used hardcoded defaults instead of existing database values when fields were not provided
  • Impact: Partial updates would overwrite existing data with defaults
  • Fix: Fetch existing record and use current values for unprovided fields

10. Error Response Utilities

Created helper function for consistent error formatting:

def create_error_response(dev_message, prod_message=None, details=None):
    """Returns environment-appropriate error messages"""
    - Development: Includes detailed error information
    - Production: Returns generic, user-friendly messages

11. Status Code Improvements

  • Added proper HTTP status codes where they were missing
  • Ensured consistency: 400 for validation errors, 404 for not found, 500 for server errors
  • All error responses now include appropriate status codes

12. Documentation Updates

  • Updated setup.md with environment-specific run commands:
    • Development: python app.py --env development
    • Production: python app.py --env production

📷 Screenshots or Visual Changes (if applicable)

[Used Incorrect Query format for testing]:

image

[Output in development while using a wrong query]:

image

[Deleting Appointment with incorrect ID in dev mode]:

image

[Provided Incorrect JSON format]:

image

[Gave Incorrect blood pressure details in dev mode]:

image

[Gave Incorrect blood pressure details in prod mode]:

image

🧪 Testing Performed

Extensive testing was conducted across all modified routes:

  • ✅ Verified all custom error handlers trigger correctly
  • ✅ Tested environment-based error responses (dev vs prod)
  • ✅ Validated all SQL operations with edge cases
  • ✅ Confirmed validation utilities reject invalid data
  • ✅ Tested route conflict resolutions
  • ✅ Verified PATCH operations behave correctly
  • ✅ Confirmed database error decorator catches all DB exceptions
  • ✅ Tested malformed JSON handling with get_json()

🏗️ Architecture Improvements

  • Separation of Concerns: Error handling logic extracted to dedicated module
  • DRY Principle: Eliminated repetitive try-catch blocks with decorator pattern
  • Consistency: Unified error response format across entire application
  • Maintainability: Centralized validation logic in utilities module
  • Scalability: Easy to add new error types and handlers

🤝 Collaboration

N/A

✅ Checklist

  • I have read the contributing guidelines.
  • I have added tests that prove my fix is effective or that my feature works.
  • I have added necessary documentation (if applicable).
  • Any dependent changes have been merged and published in downstream modules.

📋 Additional Notes for Reviewers

This PR represents a significant refactoring of the application's error handling system. While extensive, every change addresses either:

  1. A discovered bug or inconsistency
  2. Missing error handling that could cause application crashes
  3. Architectural improvements for maintainability

The changes are compatible with existing functionality while providing a robust foundation for future development. All modifications have been tested to ensure existing features continue to work as expected.

Summary by CodeRabbit

  • New Features

    • Environment-aware modes (dev/prod) with adjusted error responses.
    • New agent-facing endpoints for cache, context, and recommendations.
    • Centralized validation utilities applied across health data forms.
  • Bug Fixes

    • Unified, centralized error handling with structured error types.
    • Switched many update operations to PATCH for partial updates; consistent cache sync after mutations.
  • Documentation

    • Updated setup instructions with explicit env-mode run guidance.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 27, 2026

📝 Walkthrough

Walkthrough

Centralizes environment-aware error handling with new exception classes and a decorator; updates many backend routes to raise these errors and use PATCH for partial updates; adds validation utilities and agent endpoints in app bootstrap; updates frontend calls to PATCH; adds .env to .gitignore and updates setup docs.

Changes

Cohort / File(s) Summary
Error handling infra
Backend/error_handling/error_classes.py, Backend/error_handling/handlers.py
Adds MissingFieldError and NotFoundError exception classes and environment-aware handlers plus handle_db_errors decorator to standardize DB/custom-error responses (dev vs prod).
App bootstrap & agent API
Backend/app.py, Setup.md
Adds --env argparse selection, registers custom error handlers (including BadRequest/UnsupportedMediaType), dynamic port selection by ENV, and new agent-related endpoints; docs updated for run modes.
Validation utilities
Backend/utils.py
New validators: validate_bp_data, validate_medicine_data, validate_week_number, validate_weight_value.
Backend route updates
Backend/routes/...
Backend/routes/appointments.py, .../blood_pressure.py, .../discharge.py, .../medicine.py, .../profile.py, .../symptoms.py, .../tasks.py, .../weight.py
Routes now use @handle_db_errors, raise MissingFieldError/NotFoundError instead of inline JSON errors, switch update endpoints from PUT→PATCH, add input validation, and unify cache updates after mutations.
Frontend API method changes
Frontend/src/Screens/*.jsx, Frontend/src/services/*.js
Update update requests from PUT → PATCH across screens (BloodPressure, Calendar, Discharge, Medicine, Symptoms, Timeline, Weight) and services (ActionExecutor, ConversationContext).
Misc / config
.gitignore
Adds .env to ignore list.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Route as "Route Handler"
    participant Decor as "handle_db_errors\n(Decorator)"
    participant ErrH as "Error Handler\n(create_error_response)"
    participant DB as "Database / Cache"
    participant Response

    Client->>Route: HTTP Request (GET/POST/PATCH/DELETE)
    activate Route
    Route->>DB: validate / query / mutate
    alt Success
        DB-->>Route: data / ack
        Route-->>Client: 200/201 Success Response
    else Exception (MissingFieldError / NotFoundError / sqlite)
        Route-->>Decor: exception propagates
        Decor->>ErrH: select handler based on exception
        ErrH->>ErrH: check current_app.config['ENV']
        alt ENV == development
            ErrH-->>Response: detailed JSON (dev_message + details)
        else ENV == production
            ErrH-->>Response: generic JSON (prod_message)
        end
        Response-->>Client: 4xx/5xx Error Response
    end
    deactivate Route
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through routes and tidied the lair,

Turned scattered throws to handlers with care.
PATCH for small tweaks, validations in tow,
Dev shows full traces, prod keeps it low.
Hooray—faster fixes, now off for a carrot!

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.58% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'Feature/centralized error handling' accurately reflects the main objective of implementing centralized, environment-aware error handling across the backend.
Linked Issues check ✅ Passed The PR successfully implements all core requirements from issue #171: centralized error handlers using custom exception classes (MissingFieldError, NotFoundError), environment-aware responses (dev vs prod), consistent JSON error structure, and elimination of repeated try/except blocks across routes.
Out of Scope Changes check ✅ Passed All changes align with the scope of centralizing error handling and environment-aware configuration. Frontend HTTP method updates (PUT to PATCH) and input validation utilities are directly supporting changes needed for the backend error handling infrastructure.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Backend/routes/symptoms.py (1)

15-33: Inaccurate missing field reporting.

The condition if not (week and symptom) correctly checks if either field is missing, but MissingFieldError(['week_number', 'symptom']) always reports both fields as missing regardless of which one is actually absent. This provides misleading feedback to API consumers.

Proposed fix
-    if not (week and symptom):
-        raise MissingFieldError(['week_number', 'symptom'])
+    required = ['week_number', 'symptom']
+    missing = [field for field in required if not data.get(field)]
+    if missing:
+        raise MissingFieldError(missing)
Backend/app.py (1)

227-233: Index route has unused import and incomplete implementation.

The index() function imports and calls get_tasks() but doesn't use the result. It only returns appointment_db. This appears to be incomplete or debug code.

🐛 Suggested cleanup
 `@app.route`('/')
 def index():
     from routes.appointments import get_appointments
-    from routes.tasks import get_tasks
     appointment_db =  get_appointments()
-    task_db = get_tasks()
     return appointment_db
🤖 Fix all issues with AI agents
In `@Backend/app.py`:
- Around line 236-237: The app currently calls app.run(host='0.0.0.0',
port=port, debug=True) which forces debug mode in all environments; change this
to compute debug from app.config['ENV'] (e.g., debug = app.config['ENV'] ==
'development') and pass that debug flag to app.run, and ensure port (from
os.getenv("DEV_PORT", 5000) / os.getenv("PROD_PORT", 8000)) is converted to an
integer before use; update the invocation of app.run(...) accordingly so debug
is False in production.
- Around line 21-23: The module currently calls argparse.parse_args() at import
time (the parser variable and args = parser.parse_args()), which breaks WSGI
deployments; move the argparse.ArgumentParser creation and args =
parser.parse_args() call into the if __name__ == '__main__': block so parsing
happens only when the script is executed directly, and update any code that uses
args (e.g., server start logic) to read from the moved args inside that main
block.

In `@Backend/error_handling/error_classes.py`:
- Around line 1-7: The message attribute in MissingFieldError.__init__ uses an
unnecessary f-string prefix; update the assignment in class MissingFieldError
(method __init__) to use a plain string ("Missing required fields") or
interpolate self.field_names into the f-string (e.g., f"Missing required fields:
{self.field_names}") to remove the unused f-prefix and satisfy linting.

In `@Backend/routes/blood_pressure.py`:
- Around line 52-65: The two GET routes share the same variable segment and
collide; update the route decorators to use distinct URL prefixes so Flask can
dispatch correctly: change the decorator for get_bp_logs_by_week to use
'/blood_pressure/week/<int:week>' and change the decorator for the single-entry
handler (the function that fetches by id, e.g., get_bp_log or similar) to use
'/blood_pressure/entry/<int:id>'; keep the handler names (get_bp_logs_by_week
and the id-fetching function) and their logic unchanged, only update their
`@bp_bp.route`(...) patterns and any code that constructs links to these
endpoints.

In `@Backend/routes/profile.py`:
- Around line 88-124: The handler update_profile currently assumes a profile row
exists and uses profile['lmp'] etc., causing a crash when profile is None; add a
null check right after profile = db.execute(...).fetchone() and if profile is
None return a 404 or appropriate error JSON (e.g., {"error":"profile not
found"}) before accessing profile fields, or alternatively initialize fallback
defaults from request when profile is missing; ensure subsequent references to
profile (profile['lmp'], profile['cycleLength'], profile['periodLength'],
profile['age'], profile['weight'], profile['user_location']) are only used after
this guard so calculate_due_date(lmp, cycleLength) and the UPDATE statement
operate with validated values.

In `@Backend/routes/tasks.py`:
- Around line 57-64: The UPDATE query in routes/tasks.py is incorrectly
defaulting isOptional and isAppointmentMade to False on partial updates; change
the db.execute parameter calls to use data.get('isOptional', task['isOptional'])
and data.get('isAppointmentMade', task['isAppointmentMade']) so these flags
preserve existing values when not provided in the incoming data (same pattern
used for title/content/etc.), keeping the rest of the db.execute call and
db.commit intact.
- Around line 95-105: The two DB operations in move_to_appointment (the 'UPDATE
tasks SET isAppointmentMade = ? WHERE id = ?' and the 'INSERT INTO appointments
(...) VALUES (...)') are committed separately, breaking atomicity; change the
logic to perform both statements within a single transaction and call
db.commit() once after both execute calls (or begin a transaction and rollback
on exception), ensuring you handle exceptions to rollback if the INSERT fails so
the task update is not persisted alone.

In `@Backend/routes/weight.py`:
- Around line 89-92: The update_weight endpoint incorrectly treats
validate_week_number and validate_weight_value return values as booleans; those
validators return dicts with a "status" key like log_weight does, so update
update_weight to inspect the validators' ["status"] fields (e.g., if not
validate_week_number(week_number)["status"] or if not
validate_weight_value(weight)["status"]) and return the corresponding error
payload/message from the validator when status is False, mirroring the pattern
used in log_weight.

In `@Backend/utils.py`:
- Around line 17-34: validate_medicine_data currently skips validation for empty
strings because it checks truthiness of name/dose; change the checks to use "is
not None" and validate the local variables instead of indexing data (use name
and dose), e.g., for name: if name is not None and (not isinstance(name, str) or
len(name.strip()) == 0): errors["name"] = "Medicine name must be a non-empty
string." and similarly for dose using dose variable; keep the existing
week_number handling with validate_week_number and populate
errors["week_number"] from week_result as before.
- Around line 2-12: The validate_bp_data function currently indexes
data['week_number'], data['systolic'], and data['diastolic'] directly which
raises KeyError for PATCH/partial payloads; change the logic to first check
presence of each key (e.g., if 'week_number' in data / if 'systolic' in data /
if 'diastolic' in data) and only perform the type and range validations when the
key exists (or use data.get(...) and check for None), adding an appropriate
error message to errors when validation fails; keep the validation rules
(positive int for week_number, 50< systolic <300, 30< diastolic <200) and return
the errors dict as before.

In `@Frontend/src/services/ActionExecutor.js`:
- Around line 245-249: The rollbackUpdateAppointment function is calling the
wrong endpoint/method (PUT on /appointments/{id}) which the backend doesn’t
support; update rollbackUpdateAppointment to send a PATCH to
/update_appointment/{id} (same shape as update call) and use the same JSON
body/headers pattern as the existing updateAppointment logic so the undo uses
the correct endpoint and avoids 405 errors.
🧹 Nitpick comments (6)
Backend/routes/profile.py (1)

21-56: Inconsistent error handling pattern.

The validation mixes MissingFieldError (lines 33-34) with inline jsonify error responses (lines 36-44). For consistency with the centralized error handling approach, consider creating a custom validation error class or using a validation utility like other routes do with validate_bp_data and validate_medicine_data.

Backend/routes/tasks.py (2)

1-5: Unused imports can be cleaned up.

sqlite3 (line 1) and close_db (line 3) are imported but not used in this file. The @handle_db_errors decorator handles sqlite3 exceptions internally, and close_db is managed by the app teardown context.

♻️ Suggested cleanup
-import sqlite3
-from flask import Blueprint, jsonify, request
-from db.db import open_db,close_db
+from flask import Blueprint, jsonify, request
+from db.db import open_db
 from error_handling.error_classes import MissingFieldError, NotFoundError
 from error_handling.handlers import handle_db_errors

77-77: Consider using PATCH for consistency with other update routes.

The PR changes update endpoints from PUT to PATCH across the codebase, but move_to_appointment still uses PUT. While PUT may be semantically appropriate here (creating a new resource from an existing one), consider whether PATCH or POST would be more consistent with the PR's conventions.

Backend/app.py (1)

68-74: Unused parameter e in handle_unsupported_media.

The exception parameter is not used, unlike other error handlers that use it for environment-aware messaging. Consider using it for consistency or prefixing with underscore to indicate intentional non-use.

♻️ Suggested fix
 `@app.errorhandler`(UnsupportedMediaType)
 # This handles cases where Content-Type is not application/json
 # This error is raised by the get_json() method of the request object
-def handle_unsupported_media(e):
+def handle_unsupported_media(_e):
     return jsonify({
         "error": "Content-Type must be application/json"
     }), 415
Backend/routes/discharge.py (1)

34-36: Consider extracting duplicate db_path computation.

The db_path construction and agent retrieval logic is duplicated across add_discharge_log, update_discharge_log, and delete_discharge_log. This could be extracted to a helper or module-level constant.

♻️ Suggested refactor

Add at module level:

DB_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "database.db")

Then replace each occurrence:

-    db_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "database.db")
-    agent = get_agent(db_path)
+    agent = get_agent(DB_PATH)

Also applies to: 90-92, 109-111

Backend/routes/weight.py (1)

43-45: Consider extracting duplicate db_path and agent retrieval logic.

Similar to discharge.py, the db_path computation and get_agent() call are duplicated. This could be consolidated.

Also applies to: 105-107, 123-125

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@Backend/routes/profile.py`:
- Around line 25-33: The route handlers set_profile and update_profile call
request.get_json() then immediately use data.get(), which will raise
AttributeError when get_json() returns None; add a guard like the /agent route:
after calling request.get_json() check if data is falsy (None) and return a 400
Bad Request with a clear JSON error before any data.get() calls, and apply the
same guard in both set_profile and update_profile so missing/empty JSON payloads
produce 400 validation errors instead of triggering the generic 500 handler.
🧹 Nitpick comments (4)
Backend/routes/profile.py (1)

36-39: Keep validation errors within centralized error formatting.

These inline return jsonify(...), 400 branches bypass the environment-aware error formatting you just centralized. Prefer raising a custom validation exception or using the shared error helper so error payloads stay consistent across environments.

Also applies to: 41-44, 104-107, 109-112

Backend/utils.py (1)

2-14: Validation logic improved, but falsy values still skip checks.

Using data.get() prevents KeyError, which is good. However, the pattern if data.get('systolic') and ... means a value of 0 would skip validation entirely. While 0 is outside the valid ranges anyway, consider using explicit is not None checks for consistency:

systolic = data.get('systolic')
if systolic is not None and (not isinstance(systolic, int) or not (50 < systolic < 300)):

This makes intent clearer and aligns with how validate_medicine_data handles week_number.

Backend/routes/tasks.py (1)

27-43: Return 201 for successful resource creation.

The add_task endpoint returns 200 on success, but log_weight returns 201 for creation. For consistency and REST semantics, POST operations that create resources should return 201 Created.

♻️ Proposed fix
-    return jsonify({"status": "success", "message": "Task added"}), 200
+    return jsonify({"status": "success", "message": "Task added"}), 201
Backend/app.py (1)

68-74: Remove unused parameter or use it in the response.

The e parameter in handle_unsupported_media(e) is unused. Either remove it or include relevant details from the exception in development mode for consistency with other error handlers.

♻️ Proposed fix (option 1: use the parameter)
 `@app.errorhandler`(UnsupportedMediaType)
-# This handles cases where Content-Type is not application/json
-# This error is raised by the get_json() method of the request object
-def handle_unsupported_media(e):
-    return jsonify({
-        "error": "Content-Type must be application/json"
-    }), 415
+def handle_unsupported_media(e):
+    """Handle cases where Content-Type is not application/json."""
+    mode = app.config.get('ENV', 'development')
+    if mode == 'development':
+        return jsonify({
+            "error": "Content-Type must be application/json",
+            "details": e.description
+        }), 415
+    return jsonify({
+        "error": "Content-Type must be application/json"
+    }), 415

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@Backend/routes/profile.py`:
- Around line 118-121: The UPDATE statement in profile.py (the db.execute call
that sets dueDate, user_location, lmp, cycleLength, periodLength, age, weight)
is missing a WHERE clause and will update every row; modify that query to
include a WHERE condition (e.g., "WHERE id = ?" or "WHERE user_id = ?") and pass
the corresponding id/user_id into the parameter tuple so only the intended
profile row is updated (ensure the identifier used matches the table PK/column
and any surrounding function handling e.g., the route handler that receives the
profile id).
🧹 Nitpick comments (3)
Backend/routes/profile.py (3)

1-1: Unused import.

sqlite3 is imported but not used in this file. The database errors are handled by the @handle_db_errors decorator which imports OperationalError and DatabaseError directly.

Suggested fix
-import sqlite3
 from flask import Blueprint, jsonify, request

26-46: Inconsistent error handling approach.

The PR objective is to centralize error handling, but this function mixes inline jsonify error responses (lines 27, 39, 41, 46) with the centralized MissingFieldError exception (line 36). Consider using custom exception classes consistently for all validation errors to align with the PR's goal.

For example, you could introduce a ValidationError class for type/format validation failures, or extend MissingFieldError usage to cover these cases.


55-57: Duplicated db_path construction.

The database path construction and agent retrieval pattern is repeated in three places. Consider extracting this to a helper function or module-level constant.

Suggested refactor

Add at module level:

DB_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "database.db")

def _update_profile_cache(operation: str):
    agent = get_agent(DB_PATH)
    agent.update_cache(data_type="profile", operation=operation)

Then in each handler:

-    db_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "db", "database.db")
-    agent = get_agent(db_path)
-    agent.update_cache(data_type="profile", operation="create")
+    _update_profile_cache("create")

Also applies to: 82-84, 125-127

@Naren456
Copy link
Contributor

@aneesafatima
Great Work
It`s working correctly .
Screenshot from 2026-02-13 13-53-50
Screenshot from 2026-02-13 13-53-27

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FEATURE REQUEST: Centralized and Environment-Aware Error Handling

2 participants