feat(errors): add structured error handling with tier awareness#75
Merged
feat(errors): add structured error handling with tier awareness#75
Conversation
Add tier-aware error handling infrastructure: - tier-features.ts: GitLab tier feature map with Premium/Ultimate features - error-handler.ts: Structured error types and handleGitLabError() function - Support for TIER_RESTRICTED, PERMISSION_DENIED, NOT_FOUND, RATE_LIMITED, SERVER_ERROR, and API_ERROR error codes - Alternatives suggestions for tier-restricted features - Unit tests for both modules (46 tests) Closes #50
Add structured error response integration: - Import error handler utilities in handlers.ts - Add parseGitLabApiError() to extract status codes from error messages - Add toStructuredError() to convert errors to structured responses - Modify catch block to return structured errors for GitLab API errors - Fallback to original error format for non-API errors This enables LLMs to receive actionable error information including: - error_code (TIER_RESTRICTED, PERMISSION_DENIED, NOT_FOUND, etc.) - suggested_fix with guidance on how to resolve the issue - alternatives for tier-restricted features Part of #50
📊 Test Coverage ReportOverall Coverage: 89.91% Coverage Details
Coverage Report: View detailed coverage report
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Pull request overview
This PR adds structured error handling infrastructure with tier-awareness to help LLMs self-correct and provide actionable guidance for users on restricted GitLab tiers. The implementation includes tier feature detection, structured error response generation, and integration with MCP handlers.
Changes:
- Add
tier-features.tswith mappings of Premium/Ultimate features and their Free tier alternatives - Add
error-handler.tswith structured error types and transformation functions - Integrate structured error handling into MCP tool handler in
handlers.ts
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/tier-features.ts | Defines tier-restricted features map with Premium/Ultimate features, alternatives, and documentation URLs |
| src/utils/error-handler.ts | Implements structured error types and transformation logic from GitLab API errors to actionable responses |
| src/handlers.ts | Adds error parsing and structured error integration in the main tool handler |
| tests/unit/utils/tier-features.test.ts | Comprehensive unit tests for tier-features.ts (20 tests covering all functions) |
| tests/unit/utils/error-handler.test.ts | Comprehensive unit tests for error-handler.ts (26 tests covering all error types) |
- Add action extraction from request.params.arguments and error cause - Fix regex to handle wrapped errors (Failed to execute tool prefix) - Include rawMessage context in permission denied suggested_fix - Extract resourceId and resourceType from 404 error messages - Add tests for parseGitLabApiError, toStructuredError, and error flows
…r tests - Remove unused imports from handlers.test.ts - Add 9 direct unit tests for parseGitLabApiError function - Document TierAlternative naming convention (snake_case for JSON output) - Use context-based regex for resourceId: first tries keyword match like "Project 123", then falls back to 4+ digit numbers
- Add test for 404 errors with 4+ digit ID extraction fallback - Add test for action extraction from wrapped error cause - Add test for StructuredToolError detection in cause chain - Add tests for resolveRefs: $ref resolution, arrays, nested objects - Preserve error cause when re-throwing in tool handler - Check cause chain for StructuredToolError in toStructuredError
- Replace non-existent tool references with actual implemented tools - Add group_webhooks (Premium): list_webhooks:group, manage_webhook:group - Add epics (Premium): browse_work_items:epic, manage_work_item:epic - Add iterations (Premium): list_group_iterations - Remove placeholder entries for unimplemented tools (protected branches, code owners, security dashboard, merge trains, MR approvals) - Add NOTE comment listing planned features for future implementation - Update tier-features and error-handler tests to match new structure
Pino-pretty uses worker threads via thread-stream which prevents Jest from exiting properly. Disable transport when running tests (detected via NODE_ENV=test or JEST_WORKER_ID).
…coverage test The fs mock was too aggressive and broke pino logger which uses sonic-boom internally. Now the mock preserves actual fs functions for node_modules paths.
- Remove redundant tierFeature.tier !== "Free" check (TIER_FEATURES map only contains Premium/Ultimate entries) - Add security documentation for TLS certificate validation opt-in
Replace static TIER_FEATURES map with dynamic detection using ConnectionManager.isFeatureAvailable() and getTier(). This ensures tier restrictions are based on actual GitLab instance capabilities detected at startup. Key changes: - Add parameter-aware tier detection for work item types (EPIC, OBJECTIVE, KEY_RESULT, REQUIREMENT) using toolArgs inspection - Remove tier-features.ts and its static mapping approach - Add FEATURE_METADATA map with feature info, alternatives, docs - Update handleGitLabError signature to accept toolArgs for context - Fix handlers.ts to pass toolArgs to error handling This fixes the incorrect browse_work_items:epic matching where EPIC is a work item TYPE (parameter), not an action name.
Remove obsolete reference to deleted TierFeature interface.
Import InternalTier from GitLabVersionDetector (lowercase) and keep local GitLabTier for display (capitalized). Clarify the relationship in normalizeTier function signature and comments.
sw-release-bot bot
pushed a commit
that referenced
this pull request
Jan 21, 2026
## [6.18.0](v6.17.0...v6.18.0) (2026-01-21) ### Features * **errors:** add structured error handling with tier awareness ([#75](#75)) ([2b5088c](2b5088c)), closes [#50](#50) [#50](#50) * **mrs:** implement GitLab Suggestions API integration ([#70](#70)) ([b9ca090](b9ca090)), closes [#66](#66) * **tiers:** add action-level tier requirements for consolidated tools ([#77](#77)) ([8e5ae0e](8e5ae0e)), closes [#48](#48)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
tier-features.tsanderror-handler.tsFeatures
suggested_fixwith guidancedocs_urlandupgrade_urlfor tier-restricted errorsExample Structured Error Response
{ "error_code": "TIER_RESTRICTED", "tool": "browse_protected_branches", "action": "list", "http_status": 403, "tier_required": "Premium", "feature_name": "Protected Branches API", "message": "Protected Branches API requires GitLab Premium or higher", "suggested_fix": "Upgrade to GitLab Premium, or use one of the alternatives", "alternatives": [ { "action": "Configure via UI", "description": "Use Settings > Repository > Protected branches in GitLab UI", "available_on": "Free" } ], "docs_url": "https://docs.gitlab.com/ee/api/protected_branches.html", "upgrade_url": "https://about.gitlab.com/pricing/" }Test plan
Closes #50