Cosmos DB for NoSQL errors — 403 network, RBAC and substatus codes, 429 throttling, 404, 409, 412, 413, 449 and 503, from TypeScript
What Cosmos DB for NoSQL errors mean and what to do — the 403s (firewall path messages, missing data-plane role, 5300 control-plane calls with an Entra token, 1014 full logical partition, 403.3 during failover), 429s (RU, metadata and transient, when 1–5% is healthy), 400 missing partition key, 404/1013, 409, 412 ETag, 413 2 MB, 423, 424, 449 and 503 — plus @azure/cosmos 4.10 code with Entra auth, retries and where the status and substatus live.
markdownreferencev1M49B-PH2Gstage: operatetrust: officialtrust: fieldservice: cosmos-dbinterface: sdkinterface: anyCosmos DB 403 ForbiddenRequest originated from client IP through public internetRequest originated from client VNET through private endpointRequest blocked by Authdoes not have required RBAC permissions to perform actionreadMetadata 403substatus 5300cannot be authorized by AAD token in data planeOperation 'POST' on resource 'calls' is not allowed through Azure Cosmos DB endpointCreateLeaseContainerIfNotExistssubstatus 1014Partition key reached maximum size403.3 write region failoverCosmos DB 429Request rate is largemetadata 429hot partition normalized RU consumptionCosmos DB 400 partition key missing404 substatus 1013409 Conflict id exists412 Precondition failure etag413 Entity too large 2 MB423 Locked scale operation424 Failed dependency TransactionalBatch449 Retry With503 Service Unavailable@azure/cosmosaadCredentialsErrorResponse substatusretryAfterInMsmaxRetryAttemptCount 9maxWaitTimeInSeconds 30customer-managed key substatus 4002
Cosmos DB for NoSQL errors
In @azure/cosmos, a failed call throws ErrorResponse: code is the HTTP status, substatus the sub-code, plus activityId (give it to support), retryAfterInMs, requestCharge and diagnostics.
403 Forbidden
| Message / substatus | Cause → fix |
|---|---|
Request originated from client IP {...} through public internet. / … from client VNET through service endpoint. / … through private endpoint. | The network path isn't allowed. If the path is unexpected, fix the client (service endpoint missing on the subnet, DNS resolving the public IP instead of the private endpoint); if expected, fix public access, IP, VNet or private endpoint settings. Changes take up to 15 minutes |
Request blocked by Auth : Request is blocked because principal [<id>] does not have required RBAC permissions to perform action [Microsoft.DocumentDB/databaseAccounts/readMetadata] on resource [/]. Learn more: https://aka.ms/cosmos-native-rbac. (as reported on Microsoft Q&A) | No Cosmos data-plane role at that scope. Create a sqlRoleAssignment (Built-in Data Reader or Contributor); Azure RBAC roles, even Owner, don't help |
Forbidden (403); Substatus: 5300; The given request [PUT ...] cannot be authorized by AAD token in data plane. / Operation 'POST' on resource 'calls' is not allowed through Azure Cosmos DB endpoint | Creating or deleting databases or containers (control plane) with an Entra token. Do it through Resource Manager (Bicep, CLI, management SDK) with Contributor or DocumentDB Account Contributor. Azure Functions Cosmos trigger: set CreateLeaseContainerIfNotExists to false and create the lease container yourself |
Response status code does not indicate success: Forbidden (403); Substatus: 1014 / Partition key reached maximum size of {...} GB | One logical partition is full (20 GB): redesign the key (hierarchical keys) |
| 403.3 | Write during a manual failover: SDKs follow the new write region; raw REST clients must re-read the account |
| 403 (other) | Expired token, storage quota reached, or a stored procedure blocked for high resource use |
429 Too many requests
| Kind | What to do |
|---|---|
Request rate is large. More Request Units might be needed, so no changes were made. | The partition's RU/s are used up. 1–5% of requests as 429 with acceptable latency is healthy. Otherwise look for a hot partition (one PartitionKeyRangeId near 100% normalized RU consumption while others idle): fix the key or spread the writes; then raise RU/s or use autoscale |
The request didn't complete due to a high rate of metadata requests. | Too many database/container create, read or list calls (system-reserved RU budget). More RU/s doesn't help: cache clients and container references, back off |
The request didn't complete due to a transient service error. | Retry; support case if it lasts minutes |
The SDK retries 429s itself, by default up to 9 times within 30 seconds (connectionPolicy.retryOptions), so the metric can show 429s your code never sees.
Other status codes
| Status | Meaning → fix |
|---|---|
| 400 | Invalid JSON or query, missing required properties, a stronger consistency than the account allows, or no partition key on an operation that needs one |
| 401 | Invalid Authorization header (wrong key, bad token) |
| 404 (substatus 1013) | Item or resource doesn't exist; 1013 means a container create is still in progress: keep reading until 200 |
| 408 | A stored procedure, trigger or UDF ran too long |
| 409 | The id already exists within that partition key value: upsert, or treat as success when idempotent |
| 412 | ETag mismatch (optimistic concurrency): re-read and retry |
| 413 | Item over 2 MB |
| 423 | Another throughput scale operation is running |
| 424 | Another operation in the same transactional batch failed |
| 449 | Transient write conflict: safe to retry |
| 503 | Service or network unavailable: safe to retry |
Customer-managed key accounts add substatus 4002 (Cosmos can't reach the key; restore its Key Vault access), 4003 (key deleted; recover it), 4005 (unwrap failed, often after rotation), 4006 (key URL includes a version) and 4009 (Key Vault name doesn't resolve).
TypeScript with Entra ID
import { DefaultAzureCredential } from "@azure/identity";
import { CosmosClient, ErrorResponse } from "@azure/cosmos";
// The identity needs a Cosmos DB data-plane role assignment (Built-in Data Contributor), not an Azure RBAC role.
const client = new CosmosClient({
endpoint: `https://${process.env.COSMOS_ACCOUNT}.documents.azure.com:443/`,
aadCredentials: new DefaultAzureCredential(), // the SDK asks for <endpoint>/.default
connectionPolicy: { retryOptions: { maxRetryAttemptCount: 9, maxWaitTimeInSeconds: 30, fixedRetryIntervalInMilliseconds: 0 } },
});
const orders = client.database("shop").container("orders"); // partition key path: /customerId
type Order = { id: string; customerId: string; total: number };
export async function main(): Promise<void> {
await orders.items.upsert<Order>({ id: "o-1001", customerId: "c-42", total: 12.5 });
// Point read: id + partition key, the cheapest operation.
const { resource } = await orders.item("o-1001", "c-42").read<Order>();
console.log(resource?.total);
// Parameterised query scoped to one partition.
const { resources } = await orders.items
.query<Order>(
{ query: "SELECT * FROM c WHERE c.customerId = @c AND c.total > @t", parameters: [{ name: "@c", value: "c-42" }, { name: "@t", value: 10 }] },
{ partitionKey: "c-42" },
)
.fetchAll();
console.log(resources.length);
try {
await orders.items.create<Order>({ id: "o-1001", customerId: "c-42", total: 1 });
} catch (e) {
if (e instanceof ErrorResponse) {
// code is the HTTP status (409 here); substatus and the activity ID matter for support cases
console.error(e.code, e.substatus, e.activityId, e.retryAfterInMs);
if (e.code !== 409) throw e;
} else throw e;
}
}
The account needs disableLocalAuth: true and a data-plane role for the identity: reference/cosmos-db/access-and-modeling.md. Create databases and containers in Bicep, not from the app.