Catch unique key exception from Cosmos DB output binding

Jesse Stewart (he/him) 66 Reputation points Microsoft Employee
2020-12-31T19:30:14.463+00:00

I have an azure function with an http trigger input that uses an output binding to write a new item into my Cosmos DB database.

The collection has a unique partition key named "channel".

When I try to create a new item using an existing partition key, the output binding fails, which I would expect. However, I cannot find any way to catch the exception, so that I can return a reasonable error message to the client.

The system returns the following:

System.Private.CoreLib: Exception while executing function: Functions.HttpTrigger-CreateGame. Microsoft.Azure.DocumentDB.Core: Entity with the specified id already exists in the system.
ResponseTime: 2020-12-31T18:34:39.2292184Z, StoreResult: StorePhysicalAddress: rntbd://cdb-ms-prod-westus1-fd37.documents.azure.com:14047/apps/158aedc4-c54a-471d-b9ab-65c0310623d5/services/c6f7e4e4-c91e-48d1-b2e5-bc58946a35b3/partitions/bd4f130f-7b26-4cc3-9b64-94c68de3bfb7/replicas/132533049153863193p/, LSN: 17, GlobalCommittedLsn: 17, PartitionKeyRangeId: 0, IsValid: True, StatusCode: 409, SubStatusCode: 0, RequestCharge: 1.57, ItemLSN: -1, SessionToken: -1#17, UsingLocalLSN: False, TransportException: null, ResourceType: Document, OperationType: Upsert

While the HTTP POST response is a 500 with no additional information.

I've tried wrapping my function in try/catch blocks, in different configurations, to no avail. When I step through my code using a debugger, I see that it completes the try portion, and never falls into the catch block -- the error appears to be thrown after all of my code has finished executing.

Is there some way to catch this exception and return my own response? Otherwise the client has no way of knowing why the call failed.

Here's my http trigger function:

import { AzureFunction, Context, HttpRequest } from '@azure/functions';

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    try {
        context.bindings.gameData = JSON.stringify(req.body);

        context.res = {
            status: 201,
            headers: { 'Content-Type': 'application/json' },
            body: {
                entry:  {
                    affectedRows: 1,
                    uri: context.req.url
                },
            },
        };
    } catch (e) {
        context.log(e);
        context.res = {
            status: 400,
            headers: { 'Content-Type': 'application/json' },
            body: {
                errors: [
                    'Duplicate id',
                ],
            },
        };
    }
};

export default httpTrigger;

And here's the function.json:

{
    "bindings": [
      {
        "authLevel": "function",
        "type": "httpTrigger",
        "direction": "in",
        "name": "req",
        "methods": [
          "post"
        ],
        "route": "v1/games/"
      },
      {
        "type": "http",
        "direction": "out",
        "name": "res"
      },
      {
        "type": "cosmosDB",
        "direction": "out",
        "name": "gameData",
        "databaseName": "myDatabase",
        "collectionName": "myCollection",
        "createIfNotExists": "true",
        "connectionStringSetting": "AzureWebJobsStorage",
        "partitionKey": "channel"
      }
    ],
    "scriptFile": "../dist/HttpTrigger-CreateGame/index.js"
  }
Azure Functions
Azure Functions
An Azure service that provides an event-driven serverless compute platform.
4,953 questions
Azure Cosmos DB
Azure Cosmos DB
An Azure NoSQL database service for app development.
1,624 questions
0 comments No comments
{count} votes

Accepted answer
  1. Jaliya Udagedara 2,821 Reputation points MVP
    2020-12-31T20:38:25.653+00:00

    I've tried wrapping my function in try/catch blocks, in different configurations, to no avail. When I step through my code using a debugger, I see that it completes the try portion, and never falls into the catch block -- the error appears to be thrown after all of my code has finished executing.

    This is because the input/output bindings are not in the scope of the function.

    If it's C#, we could have come with a different approach to write to Cosmos DB, but unfortunately for JavaScript, seems it's not possible as of now.

    Please go through this GitHub issue for more information: https://github.com/Azure/azure-functions-host/issues/5006

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.