诊断和排查 Azure Cosmos DB 未找到异常Diagnose and troubleshoot Azure Cosmos DB not found

HTTP 状态代码 404 表示资源不再存在。The HTTP status code 404 represents that the resource no longer exists.

预期行为Expected behavior

有许多应用程序预期接收 404 并可正确进行处理的有效方案。There are many valid scenarios where an application is expecting a 404, and correctly handles the scenario.

对应该存在或确实存在的项返回“未找到”Not found was returned for an item that should exist or does exist

如果项应该或确实存在,则以下是返回状态代码 404 的可能原因。Below are the possible reason for a status code 404 to be returned if the item should or does exits.

1.争用条件1. Race condition

有多个 SDK 客户端实例且读取在写入之前发生。There are multiple SDK client instances and the read happened before the write.

解决方案:Solution:

  1. Cosmos DB 的默认帐户一致性为会话一致性。The default account consistency for Cosmos DB is Session consistency. 创建或更新项时,响应将返回一个会话令牌,其可以在 SDK 实例之间传递,以确保读取请求在从具有该更改的副本中进行读取。When an item is created or updated, the response will return a session token that can be passed between SDK instances to guarantee that the read request is reading from a replica with that change.
  2. 一致性级别更改为更高级别Change the consistency level to a stronger level

2.分区键和 ID 组合无效2. Invalid Partition Key and ID combination

分区键和 ID 组合无效。The partition key and ID combination are not valid.

解决方案:Solution:

修复导致错误组合的应用程序逻辑。Fix the application logic that is causing the incorrect combination.

3.项 ID 中的字符无效3. Invalid character in item ID

项被插入 Cosmos DB,并且项 ID 中带有无效字符An item is inserted into Cosmos DB with an invalid character in the item ID.

解决方案:Solution:

建议用户将 ID 更改为不包含特殊字符的其他值。It's recommended for users to change the ID to a different value that does not contain the special characters. 如果不能更改 ID,则可以对 ID 进行 Base64 编码以转义特殊字符。If changing the ID is not an option you can Base64 encode the ID to escape the special characters.

对于已经插入容器中的项,可以使用 RID 值来替换 ID,而不使用基于名称的引用。Items already inserted in the container the ID can be replaced by using RID values instead of name based references.

// Get a container reference that use RID values
ContainerProperties containerProperties = await this.Container.ReadContainerAsync();
string[] selfLinkSegments = containerProperties.SelfLink.Split('/');
string databaseRid = selfLinkSegments[1];
string containerRid = selfLinkSegments[3];
Container containerByRid = this.cosmosClient.GetContainer(databaseRid, containerRid);

// List of invalid characters are listed here.
//https://docs.microsoft.com/dotnet/api/microsoft.azure.documents.resource.id?view=azure-dotnet#remarks
FeedIterator<JObject> invalidItemsIterator = this.Container.GetItemQueryIterator<JObject>(
    @"select * from t where CONTAINS(t.id, ""/"") or CONTAINS(t.id, ""#"") or CONTAINS(t.id, ""?"") or CONTAINS(t.id, ""\\"") ");
while (invalidItemsIterator.HasMoreResults)
{
    foreach (JObject itemWithInvalidId in await invalidItemsIterator.ReadNextAsync())
    {
        // It recommend to chose a new ID that does not contain special characters, but
        // if that is not possible then it can be Base64 encoded to escape the special characters
        byte[] plainTextBytes = Encoding.UTF8.GetBytes(itemWithInvalidId["id"].ToString());
        itemWithInvalidId["id"] = Convert.ToBase64String(plainTextBytes);

        // Update the item with the new ID value using the rid based container reference
        JObject item = await containerByRid.ReplaceItemAsync<JObject>(
            item: itemWithInvalidId,
            ID: itemWithInvalidId["_rid"].ToString(),
            partitionKey: new Cosmos.PartitionKey(itemWithInvalidId["status"].ToString()));

        // Validate the new ID can be read using the original name based contianer reference
        await this.Container.ReadItemAsync<ToDoActivity>(
            item["id"].ToString(),
            new Cosmos.PartitionKey(item["status"].ToString())); ;
    }
}

4.生存时间 (TTL) 清除4. Time To Live (TTL) purge

项已设置生存时间 (TTL) 属性。The item had the Time To Live (TTL) property set. 由于生存时间已过期,项被清除。The item was purged because the time to live had expired.

解决方案:Solution:

更改生存时间以防止项被清除。Change the Time To Live to prevent the item from getting purged.

5.惰性索引编制5. Lazy indexing

惰性索引编制未跟进。The lazy indexing has not caught up.

解决方案:Solution:

等待索引编制跟进或更改索引编制策略Wait for the indexing to catch up or change the indexing policy

6.已删除父资源6. Parent resource deleted

项所在的数据库和/或容器已删除。The database and/or container that the item exists in has been deleted.

解决方案:Solution:

  1. 还原父资源或重新创建资源。Restore the parent resource or recreate the resources.
  2. 创建新资源来替换已删除的资源Create a new resource to replace the deleted resource

后续步骤Next steps