pythonamazon-web-servicesaws-lambdaamazon-redshift

Redshift cannot parse response from python lambda


I am trying to create and run a lambda function from within Redshift.

I have scaled the lambda_handler back to something very simple

def lambda_handler(event, context):
    print("Received event:", event)

    value = 42
    print("Returning value:", value, "type:", type(value))

    result = [[value]]
    print("JSON result to return:", result)

    return result

I have also tried setting result as 42 and [42].

My create external function statement is

CREATE OR REPLACE EXTERNAL FUNCTION test_fn()
RETURNS INT
VOLATILE
LAMBDA 'arn:aws:.........'
IAM_ROLE 'arn:aws:iam::........';

However I keep getting the error:

SQL Error [XX000]: ERROR: Invalid External Function Response
  Detail: 
  -----------------------------------------------
  error:  Invalid External Function Response
  code:      8001
  context:   Cannot parse External Function response
  query:     0
  location:  exfunc_data.cpp:374
  process:   padbmaster [pid=1073939252]
  -----------------------------------------------

I am using a cluster of 2 ra3.large nodes which is patched to version 191.

I am expecting Redshift to return the value 42 when calling SELECT test_fn();


Solution

  • Why Redshift can’t parse your Lambda response — and the minimal fix

    Redshift Lambda UDFs must return a JSON string whose top level has a field named results. results must be an array with one element per input row Redshift sends in event["arguments"]. If you return a bare value, a Python list, or anything that isn’t a JSON string with {"results": [...]}, Redshift throws “Cannot parse External Function response”.

    Minimal working Python handler (for a no‑arg UDF)

    import json
    
    def lambda_handler(event, context):
        # Redshift batches rows in event["arguments"]
        rows = event["arguments"]          # e.g., [ [] ] for SELECT my_fn();
        results = [42] * len(rows)         # one output per input row
        return json.dumps({"results": results})
    

    Checklist

    If you add parameters later, each “row” in event["arguments"] will be an array of those values; compute one scalar per row and place them in results.