fix: Fuel Logs API returns 500 error due to repository/service snake_case mismatch #47

Closed
opened 2026-01-18 03:56:08 +00:00 by egullickson · 0 comments
Owner

Bug Description

The Fuel Logs API (GET /api/fuel-logs) returns a 500 Internal Server Error. Users cannot view or add fuel log entries.

Root Cause

There is a snake_case/camelCase mismatch between the repository and service layers:

  1. Repository mapRow() method (fuel-logs.repository.ts:232-248) converts database snake_case columns to TypeScript camelCase properties:

    • row.user_id -> userId
    • row.created_at -> createdAt
    • row.updated_at -> updatedAt
  2. Enhanced repository methods (findByUserIdEnhanced, findByVehicleIdEnhanced, findByIdEnhanced) incorrectly call this.mapRow() on their results (lines 299-318).

  3. Service toEnhancedResponse() (fuel-logs.service.ts:273-295) expects raw database rows with snake_case properties:

    userId: row.user_id,           // expects snake_case
    createdAt: new Date(row.created_at).toISOString(),  // expects snake_case
    
  4. When toEnhancedResponse() tries new Date(row.created_at).toISOString() with row.created_at being undefined (because mapRow converted it to createdAt), it throws:

    RangeError: Invalid time value
    

Affected Code

  • backend/src/features/fuel-logs/data/fuel-logs.repository.ts - lines 299-318
  • Enhanced methods: findByVehicleIdEnhanced, findByUserIdEnhanced, findByIdEnhanced

Fix

The enhanced repository methods should return raw database rows (not call mapRow()), since the service's toEnhancedResponse() handles the snake_case to camelCase conversion.

Change:

async findByUserIdEnhanced(userId: string): Promise<any[]> {
  const res = await this.pool.query(...);
  return res.rows.map(row => this.mapRow(row));  // WRONG
}

To:

async findByUserIdEnhanced(userId: string): Promise<any[]> {
  const res = await this.pool.query(...);
  return res.rows;  // Return raw rows
}

Apply same fix to:

  • findByVehicleIdEnhanced (line 304)
  • findByUserIdEnhanced (line 312)
  • findByIdEnhanced (line 317)
  • getPreviousLogByOdometer (line 325)
  • getLatestLogForVehicle (line 333)
  • createEnhanced (line 296)
  • updateEnhanced (line 419)

Reproduction Steps

  1. Navigate to https://staging.motovaultpro.com/garage/fuel-logs
  2. Observe "Failed to load fuel logs. Please try again." error
  3. Network tab shows GET /api/fuel-logs returns 500

Scope

  • Severity: High - entire fuel logs feature is broken
  • Files to modify: 1 file (fuel-logs.repository.ts)
  • Risk: Low - straightforward fix, remove mapRow calls from enhanced methods
## Bug Description The Fuel Logs API (`GET /api/fuel-logs`) returns a 500 Internal Server Error. Users cannot view or add fuel log entries. ## Root Cause There is a snake_case/camelCase mismatch between the repository and service layers: 1. **Repository `mapRow()` method** (`fuel-logs.repository.ts:232-248`) converts database snake_case columns to TypeScript camelCase properties: - `row.user_id` -> `userId` - `row.created_at` -> `createdAt` - `row.updated_at` -> `updatedAt` 2. **Enhanced repository methods** (`findByUserIdEnhanced`, `findByVehicleIdEnhanced`, `findByIdEnhanced`) incorrectly call `this.mapRow()` on their results (lines 299-318). 3. **Service `toEnhancedResponse()`** (`fuel-logs.service.ts:273-295`) expects raw database rows with snake_case properties: ```typescript userId: row.user_id, // expects snake_case createdAt: new Date(row.created_at).toISOString(), // expects snake_case ``` 4. When `toEnhancedResponse()` tries `new Date(row.created_at).toISOString()` with `row.created_at` being `undefined` (because mapRow converted it to `createdAt`), it throws: ``` RangeError: Invalid time value ``` ## Affected Code - `backend/src/features/fuel-logs/data/fuel-logs.repository.ts` - lines 299-318 - Enhanced methods: `findByVehicleIdEnhanced`, `findByUserIdEnhanced`, `findByIdEnhanced` ## Fix The enhanced repository methods should return raw database rows (not call `mapRow()`), since the service's `toEnhancedResponse()` handles the snake_case to camelCase conversion. Change: ```typescript async findByUserIdEnhanced(userId: string): Promise<any[]> { const res = await this.pool.query(...); return res.rows.map(row => this.mapRow(row)); // WRONG } ``` To: ```typescript async findByUserIdEnhanced(userId: string): Promise<any[]> { const res = await this.pool.query(...); return res.rows; // Return raw rows } ``` Apply same fix to: - `findByVehicleIdEnhanced` (line 304) - `findByUserIdEnhanced` (line 312) - `findByIdEnhanced` (line 317) - `getPreviousLogByOdometer` (line 325) - `getLatestLogForVehicle` (line 333) - `createEnhanced` (line 296) - `updateEnhanced` (line 419) ## Reproduction Steps 1. Navigate to https://staging.motovaultpro.com/garage/fuel-logs 2. Observe "Failed to load fuel logs. Please try again." error 3. Network tab shows `GET /api/fuel-logs` returns 500 ## Scope - **Severity**: High - entire fuel logs feature is broken - **Files to modify**: 1 file (`fuel-logs.repository.ts`) - **Risk**: Low - straightforward fix, remove mapRow calls from enhanced methods
egullickson added the
status
ready
type
bug
labels 2026-01-18 03:56:18 +00:00
egullickson added
status
in-progress
and removed
status
ready
labels 2026-01-18 04:06:41 +00:00
egullickson added
status
review
and removed
status
in-progress
labels 2026-01-18 04:08:52 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: egullickson/motovaultpro#47