You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure Cosmos DB分页回传continuation token报格式错误如何解决?

Azure Cosmos DB 续传令牌分页偶发格式错误解决方案

故障根因

你遇到的偶发报错本质是续传令牌的原始值在传输、存储过程中被意外修改,或是两次查询的上下文参数不匹配,之所以是偶发,是因为只有当生成的令牌包含特殊字符、或是后台容器拓扑发生变更时才会触发,具体常见原因如下:

  • 令牌传输/存储时的特殊字符转义:续传令牌是JSON格式,内部可能包含+、/、=、空格、引号等特殊字符,若直接放在HTTP参数、前端缓存、短字段数据库中,会被自动转义或截断,导致回传的令牌和Cosmos DB返回的原始值不一致
  • 两次查询上下文不一致:分页的两次查询使用的SQL语句、查询参数、QueryRequestOptions配置(比如MaxItemCount、分区键、查询开关)、SDK版本不一致,会导致旧令牌无法被识别
  • 容器拓扑变更:Cosmos DB后台发生分区拆分、合并、数据重分布时,历史生成的续传令牌会自动失效

修复方案

1. 新增续传令牌的编解码逻辑

所有涉及令牌传输、存储的环节,统一做URL安全编码,保证令牌原始值不被修改,C#中可以直接用HttpUtility工具类处理。

2. 保证查询上下文完全一致

两次分页请求的所有查询配置必须完全相同,不得动态修改查询条件、排序规则、QueryRequestOptions下的任何参数,同时确保整个服务使用统一版本的Cosmos DB SDK。

3. 新增令牌失效降级逻辑

当捕获到令牌格式错误时,返回前端提示让用户重新加载分页数据,或是自动清空令牌从第一页重新查询即可,分区变更属于后台偶发操作,不需要特殊适配。

优化后代码示例

using System.Web;

QueryRequestOptions queryRequestOptions = new QueryRequestOptions
{
    MaxItemCount = pageSize,
    // 注意:所有查询配置必须和首次查询完全一致,不得动态修改
    PartitionKey = new PartitionKey(yourPartitionKeyValue),
    EnableScanInQuery = true
};

try
{
    // 回传的令牌先做解码,还原为Cosmos DB返回的原始值
    var decodedContinuationToken = string.IsNullOrEmpty(continuationToken) 
        ? null 
        : HttpUtility.UrlDecode(continuationToken);
    
    using (FeedIterator<TOutputDocument> resultSetIterator = _cosmosContainer.GetItemQueryIterator<TOutputDocument>(queryDefinition, decodedContinuationToken, queryRequestOptions))
    {
        if (resultSetIterator.HasMoreResults)
        {
            FeedResponse<TOutputDocument> response = await resultSetIterator.ReadNextAsync();

            if (response == null)
            {
                throw new NullReferenceException($"Unable to get response from cosmos db against query - {query}, container - {nameof(_cosmosContainer)}");
            }
            // 返回给前端/存储前先做编码,避免特殊字符被转义
            continuationToken = HttpUtility.UrlEncode(response.ContinuationToken);
            documents.AddRange(response);
        }
    }
}
catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.BadRequest && 
                                (ex.Message.Contains("Continuation token specified in the request is malformed") || 
                                 ex.Message.Contains("Invalid format for continuation token")))
{
    // 捕获令牌无效错误,返回重新加载提示,或自动触发全量重试
    throw new InvalidOperationException("分页令牌已失效,请刷新后重试", ex);
}
catch (CosmosException ex)
{
    // 其他Cosmos DB异常自行处理
    throw;
}

内容的提问来源于stack exchange,提问作者Rahul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 01:48:03