2025, Oct 15 14:31
Amazon Redshift Lambda UDF में Invalid External Function Response त्रुटि: कारण और समाधान
Redshift Lambda UDF में Invalid External Function Response त्रुटि का समाधान: results कुंजी वाली JSON लौटाएँ, event[arguments] की हर पंक्ति पर एक मान दें.
Amazon Redshift से Lambda UDF चलाने पर अक्सर “Invalid External Function Response” त्रुटि आ जाती है। Lambda में कोड ठीक से चलता है, लॉग भी सही प्रिंट होते हैं, लेकिन Redshift लौटे हुए डेटा को पार्स करने से इंकार कर देता है। आमतौर पर वजह बिज़नेस लॉजिक नहीं, बल्कि रेस्पॉन्स का स्वरूप और उसका प्रकार होता है।
समस्या का सेटअप
एक न्यूनतम हैंडलर मान लें जो एक स्थिर मान लौटाता है, और Redshift में परिभाषित एक external function। सीधे-साधे तौर पर यह कुछ ऐसा दिख सकता है।
def handle(event_obj, ctx_obj):
    print("Got payload:", event_obj)
    num = 42
    print("Sending value:", num, "kind:", type(num))
    payload = [[num]]
    print("Payload to send back:", payload)
    return payload
और Redshift में external function:
CREATE OR REPLACE EXTERNAL FUNCTION demo_fn()
RETURNS INT
VOLATILE
LAMBDA 'arn:aws:.........'
IAM_ROLE 'arn:aws:iam::........';
इसे SELECT demo_fn(); से कॉल करने पर यह त्रुटि मिलती है:
ERROR: Invalid External Function Response
Detail:
Cannot parse External Function response
असल में गड़बड़ी कहाँ है
Redshift की Lambda UDFs को बहुत विशिष्ट संरचना वाली JSON स्ट्रिंग लौटानी होती है। शीर्ष स्तर पर results नाम का फील्ड होना चाहिए, और उसकी वैल्यू एक array हो जिसमें ठीक उतने ही तत्व हों, जितनी इनपुट पंक्तियाँ Redshift event["arguments"] में बैच करता है। यदि हैंडलर कोई कच्चा मान, Python list, या ऐसा कुछ लौटाता है जो {"results": [...]} जैसी JSON स्ट्रिंग नहीं है, तो Redshift उसे पार्स नहीं कर पाता और “Cannot parse External Function response” दिखाता है।
दूसरे शब्दों में, अनुबंध सख्त है: json.dumps({"results": [...]}) लौटाएँ, जहाँ उस array की लंबाई len(event["arguments"]) के बराबर हो। बिना आर्ग्युमेंट वाले फ़ंक्शन के लिए भी Redshift event["arguments"] में पंक्तियाँ भेजता है—उदाहरण के लिए SELECT demo_fn(); चलाने पर [ [] ]—इसलिए आपके results में उस एक पंक्ति के लिए एक ही तत्व होना चाहिए।
समाधान
उम्मीद के अनुरूप लिफ़ाफ़े (envelope) के साथ JSON स्ट्रिंग लौटाएँ और यह सुनिश्चित करें कि जितने इनपुट Redshift ने भेजे हैं, उतने ही आउटपुट आप वापस दें।
import json
def handle(event_obj, ctx_obj):
    # Redshift पंक्तियों को event_obj["arguments"] में बैच करता है
    items = event_obj["arguments"]          # उदा., SELECT demo_fn(); के लिए [ [] ]
    outputs = [42] * len(items)              # हर इनपुट पंक्ति पर एक आउटपुट
    return json.dumps({"results": outputs})
यह न्यूनतम हैंडलर बिना आर्ग्युमेंट वाली उस UDF के अनुबंध को पूरा करता है जो INT लौटाती है। यदि SQL परिभाषा का रिटर्न टाइप पहले से results में रखी वैल्यू से मेल खाता है, तो उसे बदलने की ज़रूरत नहीं होती।
यह क्यों महत्वपूर्ण है
यह त्रुटि न तो permissions से जुड़ी है और न runtime से; मुद्दा रेस्पॉन्स कॉन्ट्रैक्ट का है। शीर्ष स्तर पर results कुंजी वाले सही फ़ॉर्मेट की JSON स्ट्रिंग लौटाने से “Cannot parse External Function response” जैसी विफलता नहीं होती। results array की लंबाई को event["arguments"] के अनुरूप रखने से Redshift इनपुट पंक्तियों और आउटपुट स्कैलर के बीच एक-से-एक मैपिंग बना पाता है। अंत में, SQL UDF के घोषित रिटर्न टाइप को results के मानों से मेल खाना चाहिए; जैसे यदि RETURNS INT घोषित है, तो तत्व integer होने चाहिए।
समापन
जब Redshift को Lambda से जोड़ें, तो रेस्पॉन्स envelope पर ध्यान दें। हमेशा payload को json.dumps से serialize करें, आउटपुट्स को results कुंजी के नीचे रखें, और event["arguments"] की हर इनपुट पंक्ति के लिए ठीक एक मान पैदा करें। SQL का रिटर्न टाइप इन्हीं मानों के अनुरूप रखें। ऐसा करते ही SELECT demo_fn(); अपेक्षित 42 लौटाएगा, बिना किसी parse त्रुटि के।
यह लेख StackOverflow के एक प्रश्न (लेखक: Stephen Saidani) और Pradipta Dash के उत्तर पर आधारित है।