Tracing a failed contact through flow logs: a worked example
A customer says they were sent to the wrong queue after entering their account number. The CTR tells you where the contact ended up. The flow logs tell you why, because they record every block that ran, the parameters it used and the result it returned.
Step 1: Get the logs for one contact
Flow logs are written to the log group /aws/connect/<instance-alias>, but only for flows that ran a Set logging behavior block with logging enabled. In CloudWatch Logs Insights, select that log group and run:
fields @timestamp, ContactFlowName, ContactFlowModuleType, Results, Parameters | filter ContactId = "your-contact-id" | sort @timestamp asc | limit 200
Export the results as JSON (or copy the raw events) and paste them here. The analyzer rebuilds the path block by block.
Step 2: Find where the path went wrong
Read the blocks in order. In this example the sequence is: GetUserInput (the customer typed the account number), then InvokeExternalResource (Lambda customer lookup), then CheckAttribute (tier = gold?), then SetQueue. The Lambda block's Results shows an error and the flow took the Error branch, which defaults to the general queue. So the routing is fine. The lookup failed.
Step 3: Follow it into the Lambda logs
Open the function's log group (/aws/lambda/<function-name>) at the same timestamp. Put the Connect ContactId in your function's logs, for example by logging event.Details.ContactData.ContactId on every invocation, so you can match the two log streams instantly. Paste the Lambda logs here too: the analyzer flags timeouts, cold starts and unhandled errors.
Common causes behind flow errors
- Lambda timeouts. The Invoke AWS Lambda function block waits at most 8 seconds. A slow downstream API, a cold start in a VPC, or retries inside the function can exceed that even when the function eventually succeeds. Keep functions fast, set a client timeout well under 8 seconds, and consider provisioned concurrency for critical lookups.
- Invalid response shape. For synchronous invocations Connect expects a flat set of key-value pairs. Nested objects or arrays are not accepted in the default response mode, and the block fails. Use the JSON response validation option if you need nested data.
- Response too large. Keep Lambda responses small. Return only the attributes the flow needs.
- Attribute name mismatches.
$.External.Tierversus$.External.tier: attribute keys are case-sensitive, so a check silently fails to match and takes the default branch. - Logging switched off part-way. If a transferred-to flow or module doesn't enable logging, the trace just stops. Enable logging at the start of every flow you need to troubleshoot.
Useful Logs Insights queries
# Error branches taken in the last 24 h, by flow fields ContactFlowName, ContactFlowModuleType, Results | filter Results like /Error|Failed/ | stats count(*) as errors by ContactFlowName, ContactFlowModuleType | sort errors desc # Slowest Lambda invocations (Lambda log group) filter @type = "REPORT" | stats max(@duration) as maxMs, avg(@duration) as avgMs by bin(1h)
Remember that flow logging adds to CloudWatch Logs cost. Set a retention period on the log group, for example 30 to 90 days, rather than keeping logs forever.