aws-iac-mcp-server: troubleshoot_cloudformation_deployment returns empty events (describe_events not scoped to failed OperationId)
Description
troubleshoot_cloudformation_deployment (in cloudformation_deployment_troubleshooter.py) always returns an empty cloudformation_events list — even for a stack that is clearly in a failed state (UPDATE_ROLLBACK_COMPLETE) — because it never scopes the describe_events call to the operation that actually failed.
Root cause
# src/aws-iac-mcp-server/awslabs/aws_iac_mcp_server/tools/cloudformation_deployment_troubleshooter.py
stacks = self.cfn_client.describe_stacks(StackName=stack_name)['Stacks']
...
response['raw_data']['stack_status'] = stacks[0].get('StackStatus')
...
cloudformation_events = self.cfn_client.describe_events(
StackName=stack_name, Filters={'FailedEvents': True}
)['OperationEvents']Per the DescribeEvents docs, CloudFormation groups events by Operation ID — every rollback, update, etc. is its own operation. DescribeStacks now returns a LastOperations array, e.g.:
"LastOperations": [
{"OperationType": "ROLLBACK", "OperationId": "d0f12313-..."},
{"OperationType": "UPDATE_STACK", "OperationId": "1c211b5a-..."}
]The failed resource events live under the UPDATE_STACK (or CREATE_STACK) operation — not the ROLLBACK operation, since the rollback itself typically succeeds. The tool reads describe_stacks only for StackStatus, discards LastOperations, and then calls describe_events with just StackName and no OperationId. Without an explicit OperationId, FailedEvents=true appears to scope to the latest operation only (the successful ROLLBACK), so it finds nothing — even though the preceding UPDATE_STACK operation has failed events available via describe-events --operation-id <id> --filter FailedEvents=true.
Reproduced against 1.0.11 and confirmed the bug is still present at main (current 1.0.20) — the file has had no relevant changes since it was introduced in #1836.
Steps to reproduce
- Trigger a CloudFormation stack update that fails and rolls back to
UPDATE_ROLLBACK_COMPLETE. - Call
troubleshoot_cloudformation_deployment(stack_name=..., region=...). - Observe
raw_data.stack_statuscorrectly showsUPDATE_ROLLBACK_COMPLETE, butraw_data.cloudformation_events,matched_failures, andfailed_event_countare all empty/zero, giving no indication of what actually failed.
Expected behavior
The tool should:
- Read
LastOperationsfrom thedescribe_stacksresponse. - Identify the failed operation (the one preceding a
ROLLBACK, or the operation itself if it's aCREATE/UPDATEthat failed without rollback). - Call
describe_events(OperationId=<that operation id>, Filters={'FailedEvents': True})to retrieve the actual failed resource events.
Environment
- Package:
awslabs.aws-iac-mcp-server - Version tested:
1.0.11(bug also present atmain/1.0.20) - AWS CLI/SDK: boto3 CloudFormation
describe_events/describe_stacks
Suggested fix
stacks = self.cfn_client.describe_stacks(StackName=stack_name)['Stacks']
stack = stacks[0]
response['raw_data']['stack_status'] = stack.get('StackStatus')
# Pick the most recent non-rollback operation to find what actually failed
last_operations = stack.get('LastOperations', [])
operation_id = next(
(op['OperationId'] for op in last_operations if op.get('OperationType') != 'ROLLBACK'),
last_operations[0]['OperationId'] if last_operations else None,
)
describe_events_kwargs = {'Filters': {'FailedEvents': True}}
if operation_id:
describe_events_kwargs['OperationId'] = operation_id
else:
describe_events_kwargs['StackName'] = stack_name
cloudformation_events = self.cfn_client.describe_events(**describe_events_kwargs)['OperationEvents']Happy to submit a PR with this fix if that's useful — wanted to file the issue first in case there's context I'm missing about why StackName-only scoping was chosen.
Source: awslabs/mcp