Skip to content

Commit 47322df

Browse files
Peterclaude
andcommitted
fix: resolve list_versions Pydantic validation error
Add missing fields to response models to match service layer output: - Add is_latest field to VersionInfo model - Add latest field to ListVersionsResponse model The service layer was returning these fields but strict validation (extra='forbid') was rejecting them, causing 100% failure for version listing functionality. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 9fa863a commit 47322df

File tree

3 files changed

+57
-1
lines changed

3 files changed

+57
-1
lines changed

Architecture.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,7 @@ The models package implements a **modular, function-based split** that maintains
519519
- Response formatting with consistent field naming
520520
- Integration with FastAPI automatic documentation
521521
- **Phase 2 Enhancement**: `SearchResult` and `GetItemDocResponse` now include `is_stdlib: bool` and `is_dependency: bool` fields for enhanced filtering and context
522+
- **Version Response Models**: `VersionInfo` includes `is_latest: bool` field, `ListVersionsResponse` includes `latest: str | None` field for version metadata
522523

523524
**models/version_diff.py (~245 LOC)**
524525
- Version comparison and change tracking models
@@ -3974,6 +3975,38 @@ PATH_ALIASES = {
39743975
- **Performance**: O(1) alias lookup before O(n) fuzzy matching
39753976
- **Extensible**: Alias dictionary can be expanded based on usage patterns
39763977

3978+
### Pydantic Validation Error Fix in list_versions
3979+
3980+
**Location**: `models/responses.py` - VersionInfo and ListVersionsResponse models
3981+
3982+
**Issue Description**:
3983+
The list_versions service endpoint was failing with Pydantic validation errors due to field mismatch between service layer responses and response model definitions.
3984+
3985+
**Root Cause Analysis**:
3986+
- Service layer was returning "is_latest" and "latest" fields in version data
3987+
- Response models (VersionInfo and ListVersionsResponse) didn't declare these fields
3988+
- Pydantic's strict validation rejected the extra fields, causing endpoint failures
3989+
3990+
**Fix Implementation**:
3991+
```python
3992+
# Fixed VersionInfo model
3993+
class VersionInfo(BaseModel):
3994+
version: str
3995+
yanked: bool | None = None
3996+
is_latest: bool = Field(False, description="Whether this is the latest version of the crate")
3997+
3998+
# Fixed ListVersionsResponse model
3999+
class ListVersionsResponse(BaseModel):
4000+
versions: list[VersionInfo]
4001+
latest: str | None = Field(None, description="Latest version string")
4002+
```
4003+
4004+
**Impact Assessment**:
4005+
- **Pre-Fix**: Complete failure of list_versions endpoint due to validation errors
4006+
- **Post-Fix**: Successful version listing with proper latest version metadata
4007+
- **Architectural Benefit**: Ensures service layer and response model field alignment
4008+
- **Data Integrity**: Maintains type safety while supporting version metadata requirements
4009+
39774010
### Known Architectural Issues Requiring Defensive Programming
39784011

39794012
The following section documents architectural issues identified in four key features that require defensive programming improvements to prevent runtime failures.
@@ -9188,6 +9221,11 @@ class MCPTool(BaseModel):
91889221
)
91899222
```
91909223

9224+
**Service Layer Model Alignment**:
9225+
- **Critical Requirement**: Service layer response data must exactly match response model field definitions
9226+
- **Validation Enforcement**: Pydantic models validate that service layer returns only declared fields to prevent validation errors
9227+
- **Field Consistency**: Any new fields returned by services (like `is_latest`, `latest`) must be added to corresponding response models before implementation
9228+
91919229
### Tutorial Content Embedding
91929230

91939231
Tutorial content is embedded directly in the `get_mcp_manifest()` function rather than loaded from external files, following the same pattern established by the `start_pre_ingestion` tool:

UsefulInformation.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2619,6 +2619,20 @@
26192619
"defaultImplementation": "Default CLI flag changed from 'fastmcp' to 'sdk' for new users"
26202620
},
26212621
"architecturalBenefits": "Official SDK's @server.tool() decorator pattern is cleaner and more maintainable than FastMCP conversion patterns"
2622+
},
2623+
{
2624+
"error": "Extra inputs are not permitted - list_versions Pydantic validation failure",
2625+
"rootCause": "Service layer returned 'is_latest' field in VersionInfo and 'latest' field in root response, but Pydantic models used strict validation with extra='forbid' and these fields were missing from model definitions",
2626+
"solution": "Added missing fields to Pydantic response models: 'is_latest: bool = Field(False, description=\"Whether this is the latest version of the crate\")' to VersionInfo model and 'latest: str | None = Field(None, description=\"Latest version string\")' to ListVersionsResponse model",
2627+
"context": "list_versions API endpoint failing due to mismatch between service layer output and response model definition when using strict Pydantic validation",
2628+
"problem": "Service layer included additional fields not defined in Pydantic models, causing validation errors when models used ConfigDict(extra='forbid') for security",
2629+
"prevention": "Always ensure service layer output matches response model fields exactly when using strict validation. Keep service layer and response models in sync during development",
2630+
"pattern": "When using extra='forbid' in Pydantic models, all service layer output fields must be explicitly defined in the model schema",
2631+
"dateEncountered": "2025-08-25",
2632+
"relatedFiles": ["src/docsrs_mcp/models/responses.py", "src/docsrs_mcp/service/version_service.py"],
2633+
"codeExample": "# Added to VersionInfo model:\nis_latest: bool = Field(False, description=\"Whether this is the latest version of the crate\")\n\n# Added to ListVersionsResponse model:\nlatest: str | None = Field(None, description=\"Latest version string\")\n\n# Root cause - service returned extra fields:\nresponse_data = {\n 'versions': [...],\n 'latest': '1.2.3', # This field was missing from model\n # ... other fields\n}\n\n# Each VersionInfo contained:\n{\n 'version': '1.0.0',\n 'is_latest': False, # This field was missing from model\n # ... other fields\n}",
2634+
"debuggingTechnique": "Check service layer output fields against Pydantic model definitions when using strict validation to identify missing fields",
2635+
"impact": "Fixed list_versions endpoint validation errors and ensured proper response structure for version listing functionality"
26222636
}
26232637
]
26242638
},

src/docsrs_mcp/models/responses.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,13 +118,16 @@ class VersionInfo(BaseModel):
118118
"""
119119
Crate version information.
120120
121-
Represents a single version of a crate with its yanked status.
121+
Represents a single version of a crate with its yanked status and latest indicator.
122122
"""
123123

124124
version: str = Field(..., description="Version string (e.g., '1.0.0')")
125125
yanked: bool = Field(
126126
False, description="Whether this version has been yanked from crates.io"
127127
)
128+
is_latest: bool = Field(
129+
False, description="Whether this is the latest version of the crate"
130+
)
128131

129132
model_config = strict_config
130133

@@ -303,6 +306,7 @@ class ListVersionsResponse(BaseModel):
303306

304307
crate_name: str = Field(..., description="Name of the crate")
305308
versions: list[VersionInfo] = Field(..., description="List of cached versions")
309+
latest: str | None = Field(None, description="Latest version string")
306310

307311
model_config = strict_config
308312

0 commit comments

Comments
 (0)