-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
- Package Name: @azure/cosmos
- Package Version: 4.5.1 (also tested with 4.0.0)
- Operating system: macOS 25.0.0 (also affects Linux)
- nodejs
- version: v22.14.0
- browser
- name/version: N/A
- typescript
- version: 5.x
- Is the bug related to documentation in
- README.md
- source code documentation
- SDK API docs on https://learn.microsoft.com
Describe the bug
The @azure/cosmos
SDK fails to execute PATCH operations when using Gateway connection mode. The SDK sends PATCH operations as a bare JSON array [{...}]
, but the Cosmos DB Gateway (and REST API specification) expects operations wrapped in an object {"operations": [{...}]}
. This causes all PATCH requests to fail with error 400 - Invalid request format: missing patch operations array.
This bug affects:
- Local development with the Linux emulator (which only supports Gateway mode)
- Production deployments using Gateway mode (common for firewall compatibility)
- Any application configured with
ConnectionMode.Gateway
To Reproduce
Steps to reproduce the behavior:
- Configure CosmosClient with Gateway mode:
const { CosmosClient, ConnectionMode } = require('@azure/cosmos');
const client = new CosmosClient({
endpoint: 'http://localhost:8081',
key: 'C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==',
connectionPolicy: {
connectionMode: ConnectionMode.Gateway,
enableEndpointDiscovery: false,
},
allowInsecureConnection: true,
});
- Create a document:
const container = client.database('test').container('mycontainer');
await container.items.create({
id: 'doc-1',
userId: 'user123',
value: 10,
status: 'initial'
});
- Attempt a PATCH operation (following official SDK samples):
await container.item('doc-1', 'user123').patch([
{ op: 'set', path: '/status', value: 'updated' },
{ op: 'incr', path: '/value', value: 5 }
]);
- Observe error:
Error: Invalid request format: missing patch operations array.
Status Code: 400
Expected behavior
The SDK should successfully execute PATCH operations in Gateway mode by wrapping the operations array in an { "operations": [...] }
object per the official REST API specification.
The REST API clearly states:
Body
Property Required Type Description operations Required Array Patch supports either a single, or multiple, operations that should be passed as an array
When we manually send the PATCH request with proper formatting, it succeeds:
// Manual HTTP request with correct format - WORKS ✅
fetch('http://localhost:8081/dbs/test/colls/mycontainer/docs/doc-1', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json-patch+json',
'x-ms-documentdb-partitionkey': '["user123"]',
// ... auth headers
},
body: JSON.stringify({
operations: [
{ op: 'set', path: '/status', value: 'updated' },
{ op: 'incr', path: '/value', value: 5 }
]
})
});
Screenshots
HTTP request sent by SDK (FAILS):
PATCH /dbs/test/colls/foo/docs/patch-test-1
Content-Type: application/json-patch+json
[{"op":"set","path":"/status","value":"updated"},{"op":"incr","path":"/value","value":10}]
Response:
{
"message": "Invalid request format: missing patch operations array."
}
Manual HTTP request with wrapped format (SUCCEEDS):
PATCH /dbs/test/colls/foo/docs/patch-test-1
Content-Type: application/json-patch+json
{"operations":[{"op":"set","path":"/status","value":"updated"},{"op":"incr","path":"/value","value":10}]}
Response: 200 OK
with updated document
Additional context
- This issue specifically affects Gateway mode (
ConnectionMode.Gateway
) - The Linux emulator only supports Gateway mode, making local development impossible with PATCH operations
- The SDK usage follows the official sample code: https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/cosmosdb/cosmos/samples-dev/ItemManagement.ts
- Current workaround: Implement read-modify-replace pattern instead of PATCH, which is less efficient and loses the benefits of partial updates
- The error message "missing patch operations array" suggests the Gateway is looking for the
operations
wrapper but receiving a bare array - Direct mode may handle this differently, but testing is blocked since the emulator doesn't support Direct mode
References: