You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit b7d641a
Browse filesBrowse the repository at this point in the historyBrowse files
fix(billing-cost-management): add structured error_type to bcm-pricing-calc, cost-anomaly, and cost-explorer failures (#4716)
* fix(billing-cost-management): classify ClientError failures in bcm-pricing-calc, cost-anomaly, and cost-explorer
bcm-pricing-calc: the top-level handler and get_preferences read the AWS
message from a non-existent data.error key, always falling back to str(e)
and dropping handle_aws_error's classification. A failed preferences
check (including AccessDenied) was reported only as
PREFERENCES_NOT_CONFIGURED. Error responses now carry top-level
error_type, operation, and service; the four duplicated preference
short-circuit blocks share _preferences_error_response.
cost-anomaly: the bare `raise` for non-validation ClientErrors escaped
the tool, since the sibling `except Exception` does not catch exceptions
raised from another handler, and a missing AWS message crashed the
'2024' check. All ClientErrors now route through handle_aws_error;
ValidationException keeps its tailored message and data.error_code.
cost-explorer: collapse the identical ClientError/Exception handlers and
surface error_type='client_creation_error', operation, and service at the
top level on client-creation failure.
The legacy data payload is preserved for backward compatibility.
* refactor(billing-cost-management): use BCM_PRICING_CALCULATOR_SERVICE_NAME in bcm-pricing-calc top-level error handler
* refactor(billing-cost-management): pass error_type/operation/service through format_response
Add optional keyword-only error_type, operation, and service to
format_response so error paths set the top-level classification directly
instead of post-hoc response.update calls. Existing callers are unaffected.
* fix(billing-cost-management): classify cost-anomaly validation errors instead of its unreachable ClientError block
The ClientError handler in cost_anomaly is effectively unreachable:
get_anomalies catches its own exceptions, and create_aws_client makes no
network call. Revert it to upstream and instead add top-level
error_type='validation_error', operation, and service to the local input
validation returns, which are the cost-anomaly failures users actually hit.
Copy file name to clipboardExpand all lines: src/billing-cost-management-mcp-server/CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -43,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
43
43
- Corrected AWS Compute Optimizer ECS and Lambda recommendation response field names that read non-existent SDK fields and returned null. ECS now reads `currentPerformanceRisk`, `autoScalingConfiguration`, and `projectedUtilizationMetrics` (previously the non-existent `currentPerformance`, `autoScalingGroupArn`, and `projectedPerformance`), and Lambda derives the function name from the ARN (there is no `functionName` field).
44
44
- Fixed `aws-pricing` tool error responses omitting a structured error type. Each `aws-pricing` operation caught exceptions and returned `format_response('error', ...)` (everything nested under `data`, no top-level `error_type`/`operation`), so the `handle_aws_error` call in the tool wrapper was never reached and failures surfaced without a classifiable type. Operation error paths now route through `handle_aws_error` so responses carry top-level `error_type` and `operation`, and the two non-exception "no results" cases (`get_service_attributes` service-not-found, `get_pricing_from_api` empty price list) carry `error_type='no_results'` plus `operation`. The legacy `data` payload is preserved for backward compatibility.
45
45
- Fixed `session-sql` tool error responses omitting a structured error type. `execute_session_sql` caught every failure and returned a bare `{'status': 'error', 'message': ...}` with no `error_type`/`operation`, so failures surfaced without a classifiable type. Error responses now carry top-level `error_type`, `operation` (`session_sql`), and `service` (`SQL`). The `error_type` is the exception class name (e.g. `OperationalError`, `IntegrityError`, `ValueError`) -- a fixed identifier that never contains the query text or bound values, so no query content is exposed. The legacy `status='error'` and `message` payload is preserved for backward compatibility.
46
+
- Fixed `bcm-pricing-calc`, `cost-anomaly`, and `cost-explorer` error responses missing a structured error type. `bcm-pricing-calc` read the AWS message from a non-existent `data.error` key and reported every `get_preferences` failure (including `AccessDenied`) only as `PREFERENCES_NOT_CONFIGURED`; error responses now carry top-level `error_type`, `operation`, and `service`. `cost-anomaly` local input validation (bad date format, `start_date` after `end_date`, a future `end_date`, unknown `feedback`/`total_impact_operator`, missing `total_impact_end`) now carries top-level `error_type='validation_error'`, `operation`, and `service`. `cost-explorer` client-creation failures now carry top-level `error_type='client_creation_error'`, `operation`, and `service`. The legacy `data` payload is preserved for backward compatibility.
46
47
- Fixed the AWS Compute Optimizer `get_idle_recommendations` operation rejecting `ResourceType` and `Finding` filter values whose casing differs from the idle enums (e.g. `EbsVolume` instead of `EBSVolume`, `idle` instead of `Idle`). Passed values are now normalized case-insensitively against the idle enums read from the installed botocore service model, and the response echoes the normalized filters as `applied_filters`. An `InvalidParameterValueException` now returns a structured error listing `valid_resource_type_values` and `valid_finding_values` so callers can self-correct instead of retrying the same request.
Copy file name to clipboardExpand all lines: src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/bcm_pricing_calculator_tools.py
Copy file name to clipboardExpand all lines: src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/cost_anomaly_tools.py
+27-1Lines changed: 27 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -92,13 +92,19 @@ async def cost_anomaly(
92
92
'error',
93
93
{'invalid_parameter': 'start_date'},
94
94
f'Invalid start_date format: {start_date}. Date must be in YYYY-MM-DD format.',
95
+
error_type='validation_error',
96
+
operation='cost_anomaly',
97
+
service='Cost Explorer',
95
98
)
96
99
97
100
ifnotvalidate_date_format(end_date):
98
101
returnformat_response(
99
102
'error',
100
103
{'invalid_parameter': 'end_date'},
101
104
f'Invalid end_date format: {end_date}. Date must be in YYYY-MM-DD format.',
105
+
error_type='validation_error',
106
+
operation='cost_anomaly',
107
+
service='Cost Explorer',
102
108
)
103
109
104
110
# Parse dates for validation
@@ -115,6 +121,9 @@ async def cost_anomaly(
115
121
'error',
116
122
{'start_date': start_date, 'end_date': end_date},
117
123
'Invalid date range: start_date must be before or equal to end_date.',
124
+
error_type='validation_error',
125
+
operation='cost_anomaly',
126
+
service='Cost Explorer',
118
127
)
119
128
120
129
# Check if dates are in the future
@@ -123,6 +132,9 @@ async def cost_anomaly(
123
132
'error',
124
133
{'end_date': end_date},
125
134
'Invalid end_date: Cannot request anomalies for future dates.',
135
+
error_type='validation_error',
136
+
operation='cost_anomaly',
137
+
service='Cost Explorer',
126
138
)
127
139
128
140
# Check if dates are beyond the 90-day lookback period
Copy file name to clipboardExpand all lines: src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/tools/cost_explorer_tools.py
+7-6Lines changed: 7 additions & 6 deletions
Original file line number
Diff line number
Diff line change
@@ -28,7 +28,6 @@
28
28
get_tags,
29
29
get_usage_forecast,
30
30
)
31
-
frombotocore.exceptionsimportClientError
32
31
fromfastmcpimportContext, FastMCP
33
32
fromtypingimportAny, Dict, Optional
34
33
@@ -209,13 +208,18 @@ async def cost_explorer(
209
208
ce_client=create_aws_client('ce')
210
209
exceptExceptionasclient_error:
211
210
awaitctx.error(f'Failed to create AWS client: {str(client_error)}')
211
+
error_message=f'Failed to create AWS client: {str(client_error)}'
212
212
returnformat_response(
213
213
'error',
214
214
{
215
215
'error_type': 'client_creation_error',
216
-
'message': f'Failed to create AWS client: {str(client_error)}',
Copy file name to clipboardExpand all lines: src/billing-cost-management-mcp-server/awslabs/billing_cost_management_mcp_server/utilities/aws_service_base.py
0 commit comments