By default, Lambda runs your functions in a secure VPC with access to AWS services and the internet. The VPC is owned by Lambda and does not connect to your account’s default VPC. When you connect a function to a VPC in your account, it does not have access to the internet unless your VPC provides access.
— Internet and service access for VPC-connected functions — Lambda documentation
When the AWS SDK in a Lambda function inside a VPC tries to invoke another Lambda function, it’s trying to send an HTTP POST to a public AWS Lambda endpoint, but since the subnet in which the Lambda function is hosted doesn’t have outbound internet access, all such calls timeout since the network packets never reach their destination.
If your Lambda functions don’t need to be in a VPC, keeping them out of the VPC will solve this problem. But if your Lambda functions must be in a VPC, maybe to access a private RDS database or other VPC resources, you’ll need to attach a NAT Gateway to the subnet hosting the functions. This would enable outbound internet access & thus allow Lambda to Lambda calls. Note that you also need to create a route to the gateway in your subnet’s route table after creating the gateway. Here’s a complete guide — Working with NAT gateways.
Apart from outbound internet connectivity, the calling function also needs the lambda:InvokeFunction IAM permission in its execution role. Also ensure that the security groups don’t block this traffic.
Alternate Approach
Lambda functions outside a VPC can call functions inside a VPC without any additional configuration. You can use this fact to refactor your architecture to essentially wrap every function in another function, whose only purpose it to get called & in-turn call its child function inside the VPC. All wrapper / parent functions stay outside the VPC so they call be called by other functions & they can call other functions without needing additional setup!