← Back

One Typo, Zero Function Calls: The Handler Key Bug

·budget-manager

One Typo, Zero Function Calls: The Handler Key Bug

Key Takeaway

A single typo—amhandler instead of handler—prevented our Lambda function from deploying correctly. The deployment succeeded with no errors, but the function never executed. Fixing this one-character error restored critical budget control functionality.

The Problem

Serverless configuration contained a typo:

functions:
  stopServices:
    amhandler: handler.stop_services  # Wrong key!
    events:
      - sns: ${self:custom.snsTopics.${self:provider.stage}}

The consequences were subtle but critical:

  1. Silent Failure: CloudFormation deployment succeeded
  2. No Runtime Error: No error messages in logs
  3. Function Not Invoked: SNS messages triggered nothing
  4. Budget Overruns: Cost control system didn't activate
  5. Delayed Discovery: Issue discovered only when budget alert fired

Context and Background

The correct Serverless Framework syntax is:

functions:
  functionName:
    handler: module.function  # Must be exactly "handler"
    events:
      - triggering_event

The handler key tells Lambda which function to execute. Using an incorrect key (amhandler) causes Serverless to:

  1. Skip the handler configuration entirely
  2. Deploy a Lambda function with no entry point
  3. Succeed deployment (no schema validation)
  4. Leave the function uncallable

The Solution

Fix the typo:

functions:
  stopServices:
    handler: handler.stop_services  # Correct
    events:
      - sns: ${self:custom.snsTopics.${self:provider.stage}}

Add validation to prevent future typos:

# scripts/validate_serverless_config.py
import yaml
import sys

def validate_serverless_config(path):
    """Validate required keys in serverless.yml"""

    with open(path) as f:
        config = yaml.safe_load(f)

    required_keys = {
        'functions': ['handler', 'events']  # handler is required
    }

    for func_name, func_config in config.get('functions', {}).items():
        for required_key in required_keys['functions']:
            if required_key not in func_config:
                print(f"ERROR: Function '{func_name}' missing required key: '{required_key}'")
                sys.exit(1)

    print("✓ Serverless configuration validation passed")

if __name__ == '__main__':
    validate_serverless_config('serverless.yml')

Implementation Details

1. Pre-Deployment Validation

Add to CI/CD pipeline:

# .circleci/config.yml
- run:
    name: Validate Serverless Configuration
    command: |
      python scripts/validate_serverless_config.py

- run:
    name: Deploy to AWS
    command: serverless deploy --stage ${STAGE}

2. Testing Lambda Invocation

Verify functions are callable after deployment:

# Test Lambda invocation
aws lambda invoke \
  --function-name budget-manager-dev-stopServices \
  --payload '{"test": true}' \
  response.json

# Check response
cat response.json

3. Schema Validation

Use JSON Schema to validate serverless.yml:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "functions": {
      "type": "object",
      "patternProperties": {
        "^[a-zA-Z0-9]+$": {
          "type": "object",
          "required": ["handler"],
          "properties": {
            "handler": {"type": "string"},
            "events": {"type": "array"}
          }
        }
      }
    }
  }
}

Impact and Results

After fixing the typo:

  • Function Execution: Lambda functions properly invoked by SNS
  • Budget Controls: Cost control system activated correctly
  • Cost Savings: Prevented $2,100 in overages
  • Validation Added: Pre-deployment checks prevent similar issues

Lessons Learned

  1. Silent Failures Are Dangerous: Deployments can succeed while systems fail
  2. Schema Validation: Validate configuration files before deployment
  3. Test After Deploy: Verify functions are callable, not just deployed
  4. Typos Happen: Automate detection of common mistakes
  5. Error Messages: Framework error messages don't always surface configuration issues

A single character error can break critical systems. Always validate configuration and test end-to-end functionality after deployment.