The animal config validation failures stem from a fundamental architectural mismatch between the OpenAPI code generation templates and the hexagonal architecture implementation pattern. Each regeneration breaks the controller-to-implementation connection.
Problem: The generated controllers look for specific handler functions (handle_animal_config_get) but the hexagonal architecture uses a generic routing function (handle_()).
Evidence:
- Controller template line 38:
impl_function_name = "handle_{{operationId}}" - Handlers.py line 18: Only has generic
handle_()function - Error: "cannot import name 'handlers'" when handlers.py missing or misnamed functions
Problem: Every make generate-api completely overwrites controllers, losing any manual fixes or connections to implementation.
Impact:
- Business logic connections broken after each regeneration
- Import errors appear immediately after OpenAPI spec changes
- Manual fixes are temporary and lost on next generation
Problem: Form validation expects all elements in DOM simultaneously, but tabs only render active tab elements.
Evidence:
- Validation requires 11 form element IDs across multiple tabs
- Error: "Element with ID 'max-response-length-input' not found" when on Basic Info tab
- Save button completely non-functional regardless of active tab
Modify /backend/api/templates/python-flask/controller.mustache line 47-48:
# Pattern 2: Generic handler routing
from {{package}}.impl import handlers
# Use the generic handle_ function that routes based on caller
impl_function = handlers.handle_Benefits:
- Permanent fix - survives all regenerations
- Aligns with hexagonal architecture pattern
- No manual intervention needed after regeneration
Enhance handlers.py to include specific function aliases:
# Add after line 68 in handlers.py
# Create aliases for controller compatibility
handle_animal_config_get = handle_
handle_animal_config_patch = handle_
handle_animal_list_get = handle_
# ... repeat for all operationsBenefits:
- Works with existing template
- Clear function mapping
- But requires maintenance when adding new endpoints
Replace DOM-dependent validation with React state management:
// AnimalConfig.tsx - Use controlled components
const [formData, setFormData] = useState({
name: '',
species: '',
personality: '',
maxResponseLength: 200,
// ... all fields
});
// Validation reads from state, not DOM
const validateForm = () => {
return formData; // Always available regardless of active tab
};Benefits:
- Form data always available regardless of tab
- Better React patterns
- Enables progressive validation
- Check handlers.py exists:
ls impl/handlers.py - Verify handle_ function:
grep "def handle_" impl/handlers.py - Restart API server:
make stop-api && make run-api
- Switch to all tabs once: Load data into browser memory
- Use browser dev tools: Manually set form values via console
- Temporary CSS fix: Show all tabs with
display: block !important
- ✅ Apply Controller Template Fix (Solution 1)
- ✅ Test with fresh regeneration
- ✅ Document in CLAUDE.md
- Implement React controlled components
- Add comprehensive error messages
- Create regeneration validation script
- Fully decouple generated code from implementation
- Add integration tests for controller-handler connection
- Consider moving to OpenAPI 3.1 with better code generation
After any OpenAPI regeneration, verify:
- handlers.py exists in impl/ directory
- handle_() function is present and has routing logic
- Controllers import handlers successfully
- API endpoints return data (not 501 Not Implemented)
- Frontend can load animal list
- Configuration modal opens
- Form validation completes (even if save fails)
#!/bin/bash
# backup-impl.sh
cp -r impl/ impl.backup.$(date +%Y%m%d_%H%M%S)/
make generate-api
# Verify impl/ still intact#!/bin/bash
# validate-generation.sh
python -c "from openapi_server.impl import handlers; print('✅ Handlers OK')"
curl -X GET http://localhost:8080/animal_list || echo "❌ API Failed"#!/bin/bash
# .git/hooks/pre-commit
if git diff --cached --name-only | grep -q "openapi_spec.yaml"; then
echo "⚠️ OpenAPI spec changed - remember to validate handlers after regeneration"
fiCause: handlers.py missing or moved Fix: Restore from backup or recreate with handle_() function
Cause: Handler routing broken Fix: Check handler_map in handlers.py includes all operations
Cause: Tabbed interface validation Fix: Implement React controlled components
Add these checks to your CI/CD:
- Import Test:
python -c "from openapi_server.impl import handlers" - API Health:
curl http://localhost:8080/system_health - Handler Count: Verify handler_map has all expected operations
- Frontend Build: Ensure no TypeScript errors in form components
When making OpenAPI changes:
- Before: Announce in Slack/Teams
- During: Run validation script
- After: Confirm handlers intact
- Document: Update this file with new patterns
The flakiness is 100% preventable with proper template configuration. The root cause is a mismatch between code generation assumptions and hexagonal architecture patterns. Apply Solution 1 (template fix) for immediate permanent resolution.
- OpenAPI Generator Templates:
/backend/api/templates/python-flask/ - Hexagonal Architecture Handlers:
/backend/api/src/main/python/openapi_server/impl/handlers.py - Frontend Validation:
/frontend/src/hooks/useSecureFormHandling.ts - Original Investigation:
VALIDATE-ANIMAL-CONFIG-EDIT.md