Skip to content

Error Handling

ScamShield AI is designed to always return a usable response, even when errors occur. This is critical for maintaining scammer engagement -- a failed response means the scammer moves on to a real victim.

Error Response Format

{
  "status": "error",
  "reply": "",
  "error": "Description of the error"
}
Field Type Description
status "error" Indicates an error occurred.
reply string Empty string for error responses.
error string Human-readable error description.

HTTP Status Codes

Code Meaning When
200 Success Request processed successfully. Also returned for internal errors with a stalling reply (see Graceful Degradation).
401 Unauthorized Missing or invalid x-api-key header.
400 Bad Request Request body fails Pydantic validation.
405 Method Not Allowed Request method is not POST (or OPTIONS for CORS).
429 Rate Limited Session has exceeded rate limits.
500 Internal Error Unrecoverable server error.

Graceful Degradation

ScamShield AI prioritizes engagement continuity. When an internal error occurs (e.g., Gemini API failure, Firestore timeout), the endpoint returns HTTP 200 with a stalling reply instead of an error:

{
  "status": "success",
  "reply": "Ek minute, network slow hai. Thodi der mein message karta hoon.",
  "sessionId": "session-abc-123",
  "scamDetected": false,
  "extractedIntelligence": {
    "bankAccounts": [], "upiIds": [], "phishingLinks": [],
    "phoneNumbers": [], "emailAddresses": [], "suspiciousKeywords": [],
    "ifscCodes": [], "cryptoWallets": [], "aadhaarNumbers": [],
    "panNumbers": [], "amounts": [], "caseIds": [],
    "policyNumbers": [], "orderNumbers": []
  },
  "engagementMetrics": {
    "engagementDurationSeconds": 0.0,
    "totalMessagesExchanged": 0
  },
  "agentNotes": "Error fallback: Gemini API timeout after 30s"
}

This behavior ensures:

  1. The evaluator does not score the turn as a complete failure
  2. The scammer receives a plausible stalling message
  3. The next turn can recover with a fresh request

Authentication Errors

Missing API Key

curl -X POST .../guvi_honeypot \
  -H "Content-Type: application/json" \
  -d '{"sessionId": "test", ...}'

Response (HTTP 401):

{
  "status": "error",
  "reply": "",
  "error": "Unauthorized - Invalid API key"
}

Invalid API Key

curl -X POST .../guvi_honeypot \
  -H "Content-Type: application/json" \
  -H "x-api-key: wrong-key" \
  -d '{"sessionId": "test", ...}'

Response (HTTP 401):

{
  "status": "error",
  "reply": "",
  "error": "Unauthorized - Invalid API key"
}

Dev Mode (No Key Configured)

When SCAMSHIELD_API_KEY is not set and the function is running locally (outside Cloud Run/Cloud Functions), all requests are allowed regardless of the x-api-key header. In production (K_SERVICE is set), requests are denied.

Validation Errors

Request body validation is handled by Pydantic. If the request body is malformed, the error is caught and a stalling reply is returned (HTTP 200, graceful degradation).

Missing Required Fields

If sessionId, message, or metadata is missing:

// Request (missing metadata)
{
  "sessionId": "test-001",
  "message": { "sender": "scammer", "text": "Hello", "timestamp": 1700000000 }
}

// Response (HTTP 200, graceful degradation)
{
  "status": "success",
  "reply": "Ek minute, network slow hai. Thodi der mein message karta hoon.",
  "agentNotes": "Error fallback: 1 validation error for GuviRequest..."
}

Invalid Timestamp

// Request
{
  "sessionId": "test-001",
  "message": {
    "sender": "scammer",
    "text": "Hello",
    "timestamp": -1
  },
  "metadata": { "channel": "SMS", "language": "English", "locale": "IN" }
}

// Response (HTTP 200, graceful degradation)
{
  "status": "success",
  "reply": "Ek minute, network slow hai. Thodi der mein message karta hoon.",
  "agentNotes": "Error fallback: Timestamp must be non-negative, got: -1.0"
}

Rate Limiting

Rate limiting uses Firestore atomic counters per session.

Limits

Limit Value Scope
Total messages 100 Per session (lifetime)
Messages per minute 10 Per session (sliding window)

Rate-Limited Response

When a session exceeds the limit, the endpoint returns HTTP 200 with a stalling reply:

{
  "status": "success",
  "reply": "Ek minute ruko beta, bahut zyada messages aa rahe hain. Thoda der mein baat karte hain.",
  "sessionId": "session-abc-123",
  "scamDetected": false,
  "extractedIntelligence": {
    "bankAccounts": [], "upiIds": [], "phishingLinks": [],
    "phoneNumbers": [], "emailAddresses": [], "suspiciousKeywords": [],
    "ifscCodes": [], "cryptoWallets": [], "aadhaarNumbers": [],
    "panNumbers": [], "amounts": [], "caseIds": [],
    "policyNumbers": [], "orderNumbers": []
  },
  "engagementMetrics": {
    "engagementDurationSeconds": 0.0,
    "totalMessagesExchanged": 0
  },
  "agentNotes": "Rate limited — stalling scammer"
}

Rate Limiter Failure

If the rate limiter itself fails (e.g., Firestore is temporarily unavailable), the request is allowed to proceed. This is a deliberate design choice -- it is better to process a message than to block it when the rate limiter state is unknown.

CORS

The endpoint supports CORS preflight:

  • OPTIONS requests return 204 with Access-Control-Allow-Origin: *
  • All responses include Access-Control-Allow-Origin: *
  • Allowed methods: POST, OPTIONS
  • Allowed headers: Content-Type, x-api-key

Error Codes Summary

Scenario HTTP Code status Has reply?
Successful processing 200 "success" Yes (persona response)
Internal error (graceful) 200 "success" Yes (stalling message)
Rate limited 200 "success" Yes (stalling message)
Invalid API key 401 "error" No
Wrong HTTP method 405 "error" No
Unrecoverable error 500 "error" No