Skip to content

Commit 3ad9f96

Browse files
Peterclaude
andcommitted
fix(path-alias-resolution): resolve critical schema validation errors in resolve_import
**Root Cause:** - Field name mismatch in cross_reference_service.py:183 - Service returned "type" field but ImportAlternative model expected "link_type" - Caused "10 validation errors for ResolveImportResponse" preventing path alias resolution **Technical Solution:** 1. **Schema Field Alignment**: Changed "type" → "link_type" in alternatives generation 2. **Backward Compatibility**: Added AliasChoices for robust field aliasing 3. **MCP Parameter Validation**: Added resolve_import to FastMCP schema override **Validation Results:** ✅ resolve_import('serde', 'Deserialize') → 'serde::de::Deserialize' ✅ include_alternatives boolean parameter validates correctly ✅ No more Pydantic validation errors in response serialization ✅ PATH_ALIASES system confirmed working with 105+ alias mappings **Files Changed:** - src/docsrs_mcp/services/cross_reference_service.py: Fix field name in alternatives - src/docsrs_mcp/models/cross_references.py: Add AliasChoices for link_type field - src/docsrs_mcp/mcp_server.py: Add resolve_import to tools_to_fix dictionary - Architecture.md: Document bug fix in CrossReferenceService section - UsefulInformation.json: Add comprehensive solution documentation **Impact:** Restores complete Path Alias Resolution functionality for common Rust aliases like serde::Deserialize, tokio::spawn, etc. Eliminates schema validation failures that prevented proper import resolution and suggestion generation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent c25a440 commit 3ad9f96

File tree

5 files changed

+60
-3
lines changed

5 files changed

+60
-3
lines changed

Architecture.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2754,6 +2754,39 @@ The service integrates with specialized response models for type safety and stru
27542754
- **MigrationSuggestionsResponse**: Version migration recommendations with breaking changes
27552755
- **CrossReferencesResponse**: General cross-reference queries with metadata
27562756

2757+
### Path Alias Resolution Schema Validation Bug Fix (RESOLVED)
2758+
2759+
**Critical Schema Alignment Issue Fixed**: The CrossReferenceService experienced systematic validation failures in `resolve_import` operations due to field name mismatches between the service layer and Pydantic response models.
2760+
2761+
**Root Cause Analysis**:
2762+
- Service layer returned `"type": "direct"/"reexport"` field in `cross_reference_service.py:183`
2763+
- ResolveImportResponse model expected `"link_type": "direct"/"reexport"` field
2764+
- Caused "10 validation errors for ResolveImportResponse" when `ResolveImportResponse(**result)` instantiated
2765+
2766+
**Technical Solution Implemented**:
2767+
1. **Primary Fix**: Updated field name from `"type"` to `"link_type"` in service response at line 183
2768+
2. **Robustness Enhancement**: Added `AliasChoices("link_type", "type")` to ImportAlternative model for backward compatibility
2769+
3. **FastMCP Schema Override**: Extended `tools_to_fix` dictionary with `resolve_import` tool boolean parameter handling
2770+
2771+
**Architecture Impact**:
2772+
- Cross-reference service validation pipeline now correctly aligned with Pydantic schemas
2773+
- PATH_ALIASES system confirmed working with comprehensive coverage (105+ static aliases)
2774+
- Three-tier resolution hierarchy maintains integrity: database reexports → static aliases → fuzzy fallback
2775+
- MCP client compatibility enhanced through proper schema override configuration
2776+
2777+
**Validation Results**:
2778+
-`resolve_import('serde', 'Deserialize')``"serde::de::Deserialize"` (exact alias resolution functional)
2779+
- ✅ Boolean parameter `include_alternatives` validates correctly with FastMCP overrides
2780+
- ✅ ImportAlternative schema compliance verified for alternatives array responses
2781+
- ✅ No more schema validation errors in response serialization pipeline
2782+
2783+
**Prevention Measures Applied**:
2784+
- Field name consistency validation between service layer and Pydantic models
2785+
- Comprehensive aliasing pattern implemented using `AliasChoices` for backward compatibility
2786+
- FastMCP override system extended to cover all cross-reference tools with proper parameter type handling
2787+
2788+
This fix restores complete intended functionality for path alias resolution while maintaining the existing high-performance architecture and adding robustness improvements through dual-field compatibility patterns.
2789+
27572790
### Performance Characteristics
27582791

27592792
| Operation | Typical Latency | Cache Hit Ratio | Memory Usage |

UsefulInformation.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4970,6 +4970,27 @@
49704970
"relatedFiles": ["CLAUDE.md", "deployment scripts"],
49714971
"codeExample": "# Development testing (reflects local changes):\nnohup uv run docsrs-mcp > server.log 2>&1 & echo $!\n\n# Production testing (uses cached/installed version):\nnohup uvx docsrs-mcp > server.log 2>&1 & echo $!",
49724972
"debuggingTechnique": "When testing code changes, always verify which deployment method is being used. Use 'uv run' during development to ensure immediate reflection of code modifications."
4973+
},
4974+
{
4975+
"error": "Path Alias Resolution Schema Validation Errors - 10 validation errors for ResolveImportResponse",
4976+
"rootCause": "Field name mismatch in service layer: cross_reference_service.py:183 used 'type' field while Pydantic ImportAlternative model expected 'link_type' field. Error occurred during ResolveImportResponse(**result) instantiation in MCP handler. Missing FastMCP schema override for resolve_import tool caused parameter validation issues.",
4977+
"solution": "Comprehensive three-layer fix: 1) Schema field alignment - changed cross_reference_service.py:183 from 'type': 'direct' if not alias else 'reexport' to 'link_type': 'direct' if not alias else 'reexport', 2) Backward compatibility enhancement - added validation_alias=AliasChoices('link_type', 'type') to ImportAlternative model in cross_references.py:20, 3) MCP parameter validation fix - added resolve_import to tools_to_fix dictionary with boolean parameter override in mcp_server.py:107-109",
4978+
"context": "Common aliases like serde::Deserialize not resolving due to validation failures when calling resolve_import tool. Missing link_type fields and forbidden type fields in schema validation blocked PATH_ALIASES system with 105+ alias mappings.",
4979+
"lesson": "Field name consistency crucial between service dictionaries and Pydantic model schemas. Service layer → Pydantic validation → MCP response pipeline requires careful field alignment. Use AliasChoices for robust field aliasing when changing field names.",
4980+
"pattern": "Always verify service response dictionaries match Pydantic model field names exactly. Use field aliasing for backward compatibility. Include comprehensive validation tests for all MCP tools with complex schemas. Monitor FastMCP override configuration to prevent parameter validation issues.",
4981+
"dateEncountered": "2025-09-06",
4982+
"status": "RESOLVED",
4983+
"resolution_date": "2025-09-06",
4984+
"testingResults": [
4985+
"resolve_import('serde', 'Deserialize') returns 'serde::de::Deserialize'",
4986+
"include_alternatives=true parameter validates correctly",
4987+
"No validation errors in response serialization",
4988+
"PATH_ALIASES system working with 105+ alias mappings"
4989+
],
4990+
"relatedFiles": ["src/docsrs_mcp/services/cross_reference_service.py", "src/docsrs_mcp/models/cross_references.py", "src/docsrs_mcp/mcp_server.py"],
4991+
"codeExample": "# Service layer field generation (CORRECT):\nalt = {\n \"path\": path,\n \"confidence\": conf,\n \"link_type\": \"direct\" if not alias else \"reexport\", # matches schema\n}\n\n# Pydantic model with robust aliasing:\nlink_type: str = Field(\n ..., \n validation_alias=AliasChoices(\"link_type\", \"type\"),\n serialization_alias=\"link_type\",\n description=\"Type of link (reexport, crossref, etc.)\"\n)",
4992+
"debuggingTechnique": "Test with actual MCP tool calls to verify end-to-end functionality. Use direct import tests to verify service response dictionaries match Pydantic schemas. Verify FastMCP schema override system includes all tools with complex parameter types.",
4993+
"preventionStrategy": "Create comprehensive validation tests for all MCP tools with complex schemas. Monitor service layer → Pydantic validation → MCP response pipeline for field alignment. Use AliasChoices for backward compatibility when changing field names."
49734994
}
49744995
]
49754996
}

src/docsrs_mcp/mcp_server.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ async def override_fastmcp_schemas():
104104
"control_pre_ingestion": {}, # Only has enum parameters
105105
"get_item_doc": {}, # Only has string parameters
106106
"get_module_tree": {}, # Only has string parameters
107+
"resolve_import": {
108+
"include_alternatives": "boolean", # Include alternative suggestions
109+
},
107110
}
108111

109112
# Track tools not in our fix list for monitoring

src/docsrs_mcp/models/cross_references.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from __future__ import annotations
99

10-
from pydantic import BaseModel, Field
10+
from pydantic import BaseModel, Field, AliasChoices
1111

1212
from .base import strict_config
1313

@@ -17,7 +17,7 @@ class ImportAlternative(BaseModel):
1717

1818
path: str = Field(..., description="Alternative import path")
1919
confidence: float = Field(..., description="Confidence score (0.0-1.0)")
20-
link_type: str = Field(..., description="Type of link (reexport, crossref, etc.)")
20+
link_type: str = Field(..., validation_alias=AliasChoices("link_type", "type"), serialization_alias="link_type", description="Type of link (reexport, crossref, etc.)")
2121

2222
model_config = strict_config
2323

src/docsrs_mcp/services/cross_reference_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ async def resolve_import(
180180
alt = {
181181
"path": path,
182182
"confidence": conf,
183-
"type": "direct" if not alias else "reexport",
183+
"link_type": "direct" if not alias else "reexport",
184184
}
185185
if alias:
186186
alt["alias"] = alias

0 commit comments

Comments
 (0)