Commit 525d0ea
Batch: Fixes null ErrorMessage when promoting status from MultiStatus response (#5650)
## Summary
Fixes #5649
When a transactional batch response returns **207 MultiStatus** and the
SDK promotes the status code from a failing operation (e.g., 409
Conflict), the \TransactionalBatchResponse.ErrorMessage\ was always \
ull\. This is because only \StatusCode\ and \SubStatusCode\ were
promoted from the failing operation — the \ErrorMessage\ remained
sourced from the outer 207 response, which has no error message.
## Root Cause
In \TransactionalBatchResponse.PopulateFromContentAsync()\, the status
promotion logic (lines 365–379) correctly promotes \
esponseStatusCode\ and \
esponseSubStatusCode\ from the first failing operation result, but the
\ErrorMessage\ passed to the \TransactionalBatchResponse\ constructor
was still \
esponseMessage.ErrorMessage\ — the outer 207 MultiStatus message's
error, which is always `null`.
\\\csharp
// Before (bug):
TransactionalBatchResponse response = new TransactionalBatchResponse(
responseStatusCode, // 409 - promoted from operation ✅
responseSubStatusCode, // promoted from operation ✅
responseMessage.ErrorMessage, // null from outer 207 response ❌
...);
\\\
## Fix
When promoting the status code from a failing operation, also read the
error message from the failing operation's \ResourceStream\ (which
contains the server's error body for that specific operation) and use it
as the promoted \ErrorMessage\.
\\\csharp
// After (fix):
if (result.ResourceStream != null)
{
using (StreamReader reader = new StreamReader(
result.ResourceStream, encoding: Encoding.UTF8,
detectEncodingFromByteOrderMarks: true,
bufferSize: 1024, leaveOpen: true))
{
responseErrorMessage = reader.ReadToEnd();
result.ResourceStream.Position = 0; // Reset so stream is still usable
}
}
\\\
The stream position is reset after reading so the \ResourceStream\
remains available to consumers who access individual operation results.
## Testing
Added \BatchResponseDeserializationPromotesErrorMessageAsync\ test that:
1. Creates a 409 Conflict operation result with a \ResourceStream\
containing an error body
2. Creates a second operation result with 424 FailedDependency (as the
server would)
3. Wraps them in a 207 MultiStatus response
4. Calls \FromResponseMessageAsync\ with
\shouldPromoteOperationStatus=true\
5. Asserts \StatusCode\ is promoted to 409
6. **Asserts \ErrorMessage\ is promoted from the operation's
ResourceStream** (not null)
All 103 existing batch-related unit tests continue to pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 4cbe83b commit 525d0ea
2 files changed
Lines changed: 65 additions & 2 deletions
File tree
- Microsoft.Azure.Cosmos
- src/Batch
- tests/Microsoft.Azure.Cosmos.Tests/Batch
Lines changed: 12 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
361 | 361 | | |
362 | 362 | | |
363 | 363 | | |
| 364 | + | |
364 | 365 | | |
365 | 366 | | |
366 | 367 | | |
| |||
373 | 374 | | |
374 | 375 | | |
375 | 376 | | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
376 | 387 | | |
377 | 388 | | |
378 | 389 | | |
| |||
381 | 392 | | |
382 | 393 | | |
383 | 394 | | |
384 | | - | |
| 395 | + | |
385 | 396 | | |
386 | 397 | | |
387 | 398 | | |
| |||
Lines changed: 53 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
177 | 177 | | |
178 | 178 | | |
179 | 179 | | |
180 | | - | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
181 | 233 | | |
182 | 234 | | |
183 | 235 | | |
| |||
0 commit comments