Enhance error handling and introduce new error types#2573
Conversation
This commit adds new error types for WebSub and WebBroker APIs, as well as HMAC secret management, to improve error categorization and handling. It also implements a new `Is` method for the `Error` type to allow comparison based on catalog codes rather than pointer identity. Additionally, the `FromError` and `LogAndWrite` functions are introduced to streamline error logging and response generation. Various API handlers have been updated to utilize a centralized error handling approach, enhancing maintainability and clarity across the codebase.
|
Warning Review limit reached
Next review available in: 34 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (13)
📝 WalkthroughWalkthroughThis PR replaces legacy error sentinels with typed ChangesApperror foundation
Application migration
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@CodeRabbit review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
platform-api/internal/service/subscription_plan_service.go (1)
84-89: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winReplace the remaining validation
fmt.Errorfreturns withapperror.ValidationFailed.New(...)
CreatePlanandUpdatePlanstill return plainfmt.Errorffor missinghandle/nameand invalidstatus.apperror.FromErrortreats non-catalog errors asInternal, so these validation failures will come back as 500s instead of 400s.platform-api/internal/service/subscription_plan_service.go:84-89, 176-177, 204🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@platform-api/internal/service/subscription_plan_service.go` around lines 84 - 89, Replace every validation fmt.Errorf return in CreatePlan and UpdatePlan—including missing handle, missing name, and invalid status checks—with apperror.ValidationFailed.New(...) while preserving the existing validation messages, so apperror.FromError classifies these failures as validation errors.platform-api/internal/service/llm.go (1)
1347-1361: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
nilprojectRepo(a wiring issue) is mapped toProjectNotFound, misrepresenting an internal misconfiguration as a client 404.Elsewhere in this same file/PR (
ListByProvider, line 1428-1430) and inmcp.go'sListByProject, anilrepository dependency correctly returns a generic internalfmt.Errorf, not a typed not-found. Here it returnsapperror.ProjectNotFound.New(), which will surface to clients as "project not found" (404) even though the real cause is a missing/unwired dependency — masking an operational issue as normal business traffic.🔧 Proposed fix
if projectHandle != nil && *projectHandle != "" { if s.projectRepo == nil { - return nil, apperror.ProjectNotFound.New() + return nil, fmt.Errorf("cannot resolve project handle: project repository unavailable") }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@platform-api/internal/service/llm.go` around lines 1347 - 1361, Update LLMProxyService.List so a nil s.projectRepo returns a generic internal fmt.Errorf consistent with ListByProvider and mcp.go's ListByProject, rather than apperror.ProjectNotFound.New(); preserve ProjectNotFound only for missing or mismatched projects returned by the repository.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@platform-api/internal/handler/llm_apikey.go`:
- Line 110: Update DeleteLLMProviderAPIKey to preserve typed HTTP errors by
adding an errors.As guard, matching the handling in llm_proxy_apikey.go's
DeleteAPIKey and the existing ListAPIKeys/CreateAPIKey patterns. Ensure
apperror.ArtifactNotFound, apperror.LLMProviderAPIKeyNotFound, and
apperror.LLMProviderAPIKeyForbidden are returned directly, while only
unrecognized errors are passed to serviceError.
In `@platform-api/internal/handler/secret_integration_test.go`:
- Around line 925-927: Update the error message in the test assertion checking
apperror.ValidationFailed so it names ValidationFailed instead of the stale
ErrSecretRefMissing identifier; modify the relevant assertion in the secret
integration test.
In `@platform-api/internal/service/application.go`:
- Around line 204-214: Change the empty projectHandle branch in the relevant
application service method to return apperror.ValidationFailed.New() instead of
apperror.ProjectNotFound.New(), while preserving ProjectNotFound for a nil
project returned by GetProjectByHandleAndOrgID.
In `@platform-api/internal/utils/mcp.go`:
- Around line 293-296: Update the unauthorized response handling in the MCP
initialize request to use apperror.Unauthorized.New() instead of
apperror.ValidationFailed.New(), preserving the existing user-facing and log
messages so upstream 401 authentication failures produce the standard 401
payload.
---
Outside diff comments:
In `@platform-api/internal/service/llm.go`:
- Around line 1347-1361: Update LLMProxyService.List so a nil s.projectRepo
returns a generic internal fmt.Errorf consistent with ListByProvider and
mcp.go's ListByProject, rather than apperror.ProjectNotFound.New(); preserve
ProjectNotFound only for missing or mismatched projects returned by the
repository.
In `@platform-api/internal/service/subscription_plan_service.go`:
- Around line 84-89: Replace every validation fmt.Errorf return in CreatePlan
and UpdatePlan—including missing handle, missing name, and invalid status
checks—with apperror.ValidationFailed.New(...) while preserving the existing
validation messages, so apperror.FromError classifies these failures as
validation errors.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: fc6fcdb3-6593-494c-bedc-1a5a50d76348
📒 Files selected for processing (87)
platform-api/internal/apperror/apperror.goplatform-api/internal/apperror/apperror_test.goplatform-api/internal/apperror/catalog.goplatform-api/internal/apperror/codes.goplatform-api/internal/apperror/respond.goplatform-api/internal/constants/error.goplatform-api/internal/handler/api.goplatform-api/internal/handler/api_deployment.goplatform-api/internal/handler/application.goplatform-api/internal/handler/artifact_guard_response.goplatform-api/internal/handler/gateway.goplatform-api/internal/handler/gateway_internal.goplatform-api/internal/handler/llm.goplatform-api/internal/handler/llm_apikey.goplatform-api/internal/handler/llm_deployment.goplatform-api/internal/handler/llm_proxy_apikey.goplatform-api/internal/handler/mcp.goplatform-api/internal/handler/mcp_deployment.goplatform-api/internal/handler/project.goplatform-api/internal/handler/secret.goplatform-api/internal/handler/secret_integration_test.goplatform-api/internal/handler/service_error.goplatform-api/internal/handler/subscription_handler.goplatform-api/internal/handler/subscription_plan_handler.goplatform-api/internal/middleware/error_mapper.goplatform-api/internal/repository/custom_policy.goplatform-api/internal/repository/deployment.goplatform-api/internal/repository/llm.goplatform-api/internal/repository/secret.goplatform-api/internal/repository/secret_test.goplatform-api/internal/repository/subscription_repository.goplatform-api/internal/service/api.goplatform-api/internal/service/api_test.goplatform-api/internal/service/apikey.goplatform-api/internal/service/application.goplatform-api/internal/service/application_test.goplatform-api/internal/service/artifact_guard.goplatform-api/internal/service/artifact_import.goplatform-api/internal/service/artifact_import_lifecycle_test.goplatform-api/internal/service/artifact_import_llm_provider.goplatform-api/internal/service/artifact_import_llm_proxy.goplatform-api/internal/service/artifact_import_test.goplatform-api/internal/service/artifact_runtime_immutable_test.goplatform-api/internal/service/custom_policy_test.goplatform-api/internal/service/deployment.goplatform-api/internal/service/deployment_test.goplatform-api/internal/service/deployment_undeploy_guard_test.goplatform-api/internal/service/gateway.goplatform-api/internal/service/gateway_internal.goplatform-api/internal/service/llm.goplatform-api/internal/service/llm_apikey.goplatform-api/internal/service/llm_deployment.goplatform-api/internal/service/llm_provider_template_test.goplatform-api/internal/service/llm_proxy_apikey.goplatform-api/internal/service/llm_secret_validation_test.goplatform-api/internal/service/llm_test.goplatform-api/internal/service/mcp.goplatform-api/internal/service/mcp_deployment.goplatform-api/internal/service/mcp_test.goplatform-api/internal/service/policy_validation.goplatform-api/internal/service/policy_validation_test.goplatform-api/internal/service/secret_service.goplatform-api/internal/service/secret_service_test.goplatform-api/internal/service/subscription_plan_service.goplatform-api/internal/service/subscription_service.goplatform-api/internal/utils/handle.goplatform-api/internal/utils/mcp.goplatform-api/internal/webhook/handlers_application.goplatform-api/internal/webhook/handlers_subscription.goplatform-api/internal/webhook/receiver.goplatform-api/plugins/eventgateway/handler/artifact_guard_response.goplatform-api/plugins/eventgateway/handler/catalog_error_response.goplatform-api/plugins/eventgateway/handler/catalog_error_response_test.goplatform-api/plugins/eventgateway/handler/webbroker_api.goplatform-api/plugins/eventgateway/handler/webbroker_api_deployment.goplatform-api/plugins/eventgateway/handler/webbroker_apikey.goplatform-api/plugins/eventgateway/handler/websub_api.goplatform-api/plugins/eventgateway/handler/websub_api_deployment.goplatform-api/plugins/eventgateway/handler/websub_api_hmac_secret.goplatform-api/plugins/eventgateway/handler/websub_apikey.goplatform-api/plugins/eventgateway/plugin.goplatform-api/plugins/eventgateway/service/helpers.goplatform-api/plugins/eventgateway/service/webbroker_api.goplatform-api/plugins/eventgateway/service/webbroker_api_deployment.goplatform-api/plugins/eventgateway/service/websub_api.goplatform-api/plugins/eventgateway/service/websub_api_deployment.goplatform-api/plugins/eventgateway/service/websub_api_hmac_secret.go
💤 Files with no reviewable changes (3)
- platform-api/plugins/eventgateway/handler/artifact_guard_response.go
- platform-api/internal/handler/artifact_guard_response.go
- platform-api/internal/constants/error.go
This commit enhances error handling across multiple services and handlers by replacing generic error messages with specific validation error types. Changes include updating error responses in the LLM provider API key deletion, project handle validation, and subscription plan creation and updates. Additionally, the MCP server initialization now returns a more descriptive unauthorized error. These improvements aim to provide clearer feedback for API consumers and streamline error management throughout the codebase.
…Internal API This commit introduces a new InternalErrorResponse struct to standardize error responses for the Gateway Internal API. The error handling in the GatewayInternalAPIHandler has been updated to utilize this new structure, ensuring consistent error messages across various endpoints. This change enhances clarity for API consumers and improves maintainability by separating internal error representations from public API responses.
This commit updates the portal API's error response structure by replacing the generic ErrorResponse schema with a more detailed Error schema. The new schema includes specific fields for status, code, message, and trackingId, providing clearer and more consistent error messages for API consumers. Additionally, the descriptions for various error responses have been enhanced to improve clarity regarding authentication failures and server errors.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@platform-api/internal/handler/gateway_internal.go`:
- Around line 116-134: Unify the client-facing authentication failure response
in the handler’s missing api-key branch and VerifyToken error branch. Keep the
existing differentiated logging, but make both paths return the exact same HTTP
401 status and dto.NewInternalErrorResponse payload, using one consistent
message such as “Invalid or expired API key.”
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 10493253-08b7-4ce7-9c7a-f1c840902809
📒 Files selected for processing (5)
platform-api/internal/dto/gateway_internal_error.goplatform-api/internal/handler/gateway_internal.goplatform-api/internal/service/artifact_import.goplatform-api/internal/service/artifact_import_test.goplatform-api/resources/portal-api.yaml
🚧 Files skipped from review as they are similar to previous changes (2)
- platform-api/internal/service/artifact_import.go
- platform-api/internal/service/artifact_import_test.go
…er validation failures Updated tests to reflect changes in error handling for missing additional providers and input validation. Replaced constants with appropriate apperror types for better clarity and consistency in error responses.
This commit adds new error types for WebSub and WebBroker APIs, as well as HMAC secret management, to improve error categorization and handling. It also implements a new
Ismethod for theErrortype to allow comparison based on catalog codes rather than pointer identity. Additionally, theFromErrorandLogAndWritefunctions are introduced to streamline error logging and response generation. Various API handlers have been updated to utilize a centralized error handling approach, enhancing maintainability and clarity across the codebase.