-
Notifications
You must be signed in to change notification settings - Fork 0
[Phase 1] Improve Error Handling for Server Validation Responses #43
Copy link
Copy link
Closed as not planned
Labels
Description
Overview
Following the architectural review of PR #42, we've identified that client-side validation in an API wrapper is an anti-pattern. The Grocy server is the single source of truth for validation rules. Our client library should focus on:
- Properly handling and presenting server validation errors
- Protecting the HTTP client from malformed inputs
- Providing good developer experience through TypeScript types (Phase 2)
Current State
- Generic error handling that doesn't parse Grocy's validation responses
- No distinction between different types of errors (validation, auth, network, etc.)
- Poor developer experience when server rejects requests
Requirements
1. Parse Grocy API Error Responses
// Current: Generic error
Error: Request failed with status 400
// Desired: Parsed validation error
GrocyValidationError: Invalid product data
- name: Field is required
- location_id: Must be a valid location ID
- qu_id_stock: Must be a valid quantity unit ID2. Error Classification
Create specific error classes for different scenarios:
class GrocyError extends Error {
constructor(message, statusCode, details) {
super(message);
this.statusCode = statusCode;
this.details = details;
Object.freeze(this);
}
}
class GrocyValidationError extends GrocyError {
constructor(message, validationErrors) {
super(message, 400, validationErrors);
this.validationErrors = Object.freeze(validationErrors);
}
}
class GrocyAuthenticationError extends GrocyError {
constructor(message = 'Invalid or missing API key') {
super(message, 401);
}
}
class GrocyNotFoundError extends GrocyError {
constructor(resource, id) {
super(`${resource} with ID ${id} not found`, 404);
}
}3. Minimal Client Protection
Only validate what could break our HTTP client:
function validateClientConfig(apiUrl, apiKey) {
// Protect against malformed URLs that would crash fetch()
try {
new URL(apiUrl);
} catch (e) {
throw new Error('Invalid API URL format');
}
// Basic API key format check
if (!apiKey || typeof apiKey !== 'string') {
throw new Error('API key must be a non-empty string');
}
}4. Enhanced Error Messages
Transform Grocy's error responses into helpful messages:
async function handleApiError(response) {
const contentType = response.headers.get('content-type');
if (contentType?.includes('application/json')) {
const error = await response.json();
// Parse Grocy's specific error format
if (response.status === 400 && error.error_details) {
throw new GrocyValidationError(
error.error_message || 'Validation failed',
error.error_details
);
}
}
// Generic error fallback
throw new GrocyError(
`Request failed with status ${response.status}`,
response.status
);
}5. Preserve Immutability
All error objects must be immutable following our v1.0.0 principles:
- Use
Object.freeze()on all error objects - No mutation of error properties after creation
- Error details should be read-only
Implementation Notes
- Research Grocy's actual error response format by testing various failure scenarios
- Document the error format for future reference
- Ensure backward compatibility - existing error handling should continue to work
- Follow immutable patterns established in PR Phase 1: Input Validation and Immutable Responses #25
Success Criteria
- All Grocy error types properly classified and parsed
- Helpful error messages that guide developers to solutions
- Immutable error objects throughout
- No client-side business logic validation
- Minimal performance impact (<1ms overhead)
- Comprehensive tests for error scenarios
- Documentation of Grocy's error response formats
Not in Scope
- Client-side validation of business rules (that's the server's job)
- TypeScript types (Phase 2)
- Retry logic (Issue [Phase 1] Add Error Handling and Retry Logic (Issue #2) #41)
Related Issues
- Replaces [Phase 1] Add Input Validation to All API Methods (Issue #1) #40 (Input Validation) with correct architectural approach
- Related to [CRITICAL] No Error Handling or Retry Logic - Production Reliability Risk #2 (Error Handling and Retry Logic)
- Will be enhanced by [Phase 1] Add Error Handling and Retry Logic (Issue #2) #41 (Phase 2 TypeScript migration)
"Let the server validate. Let the client present errors beautifully."
Reactions are currently unavailable