Azure Durable function : Runtime Exception with non-None return value

Question:

I have been facing an issue with Azure Durable functions, which when executed from my laptop machine runs fine. When i deploy the code , i am being popped up with an runtime exception .

Here is the main orchestrator flow

#ProcessBlob and generate a list
customers = yield context.call_activity('PreProcessZcrdetail', blobToProcess)

//Split customer into chunk and upload into an API
upload_tasks = []
    for idx in range(0, batch_count):
        input = []
        input.append(bearer_token)
        input.append(get_chunk(end_customer=end_customers,
                    batch_size=threshold, index=idx * threshold))
        upload_tasks.append(
            context.call_activity("MultiProcDataUpload", input_=input))

job_details = yield context.task_all(upload_tasks)

#Sub Orches to dowbload the data
provisioning_tasks = []
provision_task = context.call_sub_orchestrator("download", job_details , f"{context.instance_id}:0")
provisioning_tasks.append(provision_task)
rsp = yield context.task_all(provisioning_tasks)

sub orchestrator looks like this

def orchestrator_function(context: df.DurableOrchestrationContext):

    //Delay for 10 mins so that the data is available
    deadline = context.current_utc_datetime + timedelta(minutes=10)
    yield context.create_timer(deadline)
    
    status_task = []
    for job in job_details:
        status_task.append(context.call_activity("MultiProcDataCheckStaus", input_=job))

    //Get download URL
    status_details = yield context.task_all(status_task)
    status = status_details

    #write to blob
    download_task = []
    for detail in status:
        download_task.append(context.call_activity("MultiProcDataDownload", input_=detail))

    download_status = yield context.task_all(download_task) 

    #Ack file creation`
    ack_data = {}
    ack_data["type"] = "multi"
    ack_status = yield context.call_activity("CreateAck", input_=ack_data)
    return "Done download"
    
main = df.Orchestrator.create(orchestrator_function)

Function.json for the MultiProcDataDownload Activity call

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "input",
      "type": "activityTrigger",
      "direction": "in"
    },
    {
      "name": "outputblobmtch",
      "type": "blob",
      "direction": "out",
      "dataType": "binary",
      "path": "output/multiproc_output/{DateTime:yyyy}-{DateTime:MM}-{DateTime:dd}/mp_match_{rand-guid}.txt",
      "connection": "AzureWebJobsStorage"
    } ,
    {
      "name": "outputblobnomtch",
      "type": "blob",
      "direction": "out",
      "dataType": "binary",
      "path": "output/multiproc_output/{DateTime:yyyy}-{DateTime:MM}-{DateTime:dd}/mp_nomatch_{rand-guid}.txt",
      "connection": "AzureWebJobsStorage"
    }
  ]
}

Why do i get an exception stating a non-None value was returned ? I tried handling the exception but this is all that i can capture in logs and doesn’t help me debug anymore.

Can’t use rand-guid in the output binding ? Again the code when run from my local runs perfectly fine.
Any leads would be apperciated.

6958e08f9c0d4b1cb352cb195e9c737c:0: Orchestration completed with a 'Failed' status and 3664 bytes of output. Details: Message: Activity function 'MultiProcDataDownload' failed:  RuntimeError: function 'MultiProcDataDownload' without a $return binding returned a non-None value 
 {"$type":"System.Exception, System.Private.CoreLib","ClassName":"System.Exception","Message":" RuntimeError: function 'MultiProcDataDownload' without a $return binding returned a non-None value","Data":null,"InnerException":{"$type":"Microsoft.Azure.WebJobs.Script.Workers.Rpc.RpcException, Microsoft.Azure.WebJobs.Script","IsUserException":false,"RemoteStackTrace":"  File "/azure-functions-host/workers/python/3.9/LINUX/X64/azure_functions_worker/dispatcher.py", line 453, in _handle__invocation_requestn    raise RuntimeError(f'function {fi.name!r} without a $return 'n","RemoteMessage":"RuntimeError: function 'MultiProcDataDownload' without a $return binding returned a non-None value","RemoteTypeName":null,"Message":"Result: FailurenException: RuntimeError: function 'MultiProcDataDownload' without a $return binding returned a non-None valuenStack:   File "/azure-functions-host/workers/python/3.9/LINUX/X64/azure_functions_worker/dispatcher.py", line 453, in _handle__invocation_requestn    raise RuntimeError(f'function {fi.name!r} without a $return 'n","Data":{"$type":"System.Collections.ListDictionaryInternal, System.Private.CoreLib"},"InnerException":null,"HelpLink":null,"Source":"System.Private.CoreLib","HResult":-2146233088,"StackTrace":"   at Microsoft.Azure.WebJobs.Script.Description.WorkerFunctionInvoker.InvokeCore(Object[] parameters, FunctionInvocationContext context) in /src/azure-functions-host/src/WebJobs.Script/Description/Workers/WorkerFunctionInvoker.cs:line 96n   at Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase.Invoke(Object[] parameters) in /src/azure-functions-host/src/WebJobs.Script/Description/FunctionInvokerBase.cs:line 82n   at Microsoft.Azure.WebJobs.Script.Description.FunctionGenerator.Coerce[T](Task`1 src) in /src/azure-functions-host/src/WebJobs.Script/Description/FunctionGenerator.cs:line 225n   at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.InvokeAsync(Object instance, Object[] arguments) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs:line 52n   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeWithTimeoutAsync(IFunctionInvoker invoker, ParameterHelper parameterHelper, CancellationTokenSource timeoutTokenSource, CancellationTokenSource functionCancellationTokenSource, Boolean throwOnTimeout, TimeSpan timerInterval, IFunctionInstance instance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 581n   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstanceEx instance, ParameterHelper parameterHelper, ILogger logger, CancellationTokenSource functionCancellationTokenSource) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 527n   at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(IFunctionInstanceEx instance, FunctionStartedMessage message, FunctionInstanceLogEntry instanceLogEntry, ParameterHelper parameterHelper, ILogger logger, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 306"},"HelpURL":null,"StackTraceString":null,"RemoteStackTraceString":null,"RemoteStackIndex":0,"ExceptionMethod":null,"HResult":-2146233088,"Source":null,"WatsonBuckets":null}, StackTrace:    at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
Asked By: Garfield

||

Answers:

name property in the function.json is incorrect. Set the name property in function.json to $return. This will bind the output of the activity function to the object.

function.json:

{
"name": "$return",
"type": "blob",
"direction": "out",
"path": "output-container/{id}"

}

def main(input: azure.functions.InputStream) -> str:
return json.dumps({
    'name': input.name,
    'length': input.length,
    'content': input.read().decode('utf-8')
})

find more info here: https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-return-value?tabs=python

Answered By: Aravindakumar S

It looks like an azure function runtime issue with the runtime version of 4.9.*

Tested by downgrading to 3.X and it works fine, in the local environment the runtime was 4.7.*

Azure Functions Core Tools
Core Tools Version:       4.0.4670 Commit hash: N/A  (64-bit)
Function Runtime Version: 4.7.2.18626
Answered By: Garfield