INTEGRATION TROUBLESHOOTING
Handle Dataverse 204 No Content without a JSON parsing error
Accept an empty successful response, keep its row identity, and test throttling and precondition failures separately.
Provider documentation checked 8 November 2026. Examples below use fixed synthetic fixtures; no request runs from this page.
The create succeeded. Your JSON parser failed.
A connector sends an Account create, receives HTTP 204, then reports an exception because its success handler calls response.json(). There is no JSON document to parse. Treating that parsing exception as a failed create can lead to an unnecessary second write.
Provider contract: Microsoft's basic create example returns 204 with no response body and identifies the new row in OData-EntityId. A successful PATCH update can also return 204; do not require a create identity header on every update.
Requesting Prefer: return=representation is a different contract. Microsoft's create-with-data example returns 201 and JSON, without the create identity header. An empty 204 is not a broken version of that representation response.
Reproduce the empty success on your own receiver
- In an existing workspace, install Microsoft Dataverse Accounts API. Select Create Account → Account row created (
dataverse-account-created). Keep default fixture mode; no lifecycle is needed. - Copy that installation's receiver URL into your local test configuration. It is the NotTheRealAPI
/r/<your-receiver-token>prefix followed by the operation path shown below. Replace the placeholder locally; never paste a private receiver URL into public logs or use real Microsoft credentials. - Send the generated request below. Record the status, response headers and empty body before running your client's deserialisation step.
- In the installed module's request inspection, check the captured POST path, synthetic headers and JSON body, then the selected response status. Compare the response headers you received with the example. A 204 must not require a JSON body to pass.
Create Account: Account row created
Documented Synthetic illustrative example from the catalogue, not a live capture. Run only after installing your own receiver. Replace <your-receiver-token> locally; no request is sent from this page.
HTTP 204 · No response body
curl / Bash request
printf '%s' '{"name":"Example Test Co"}' | \
curl -i -X POST \
'https://nottherealapi.com/r/<your-receiver-token>/api/data/v9.2/accounts' \
-H 'Authorization: Bearer synthetic-microsoft-dataverse-token' \
-H 'Accept: application/json' \
-H 'OData-Version: 4.0' \
-H 'OData-MaxVersion: 4.0' \
-H 'Content-Type: application/json' \
--data-binary @-PowerShell request
$body = '{"name":"Example Test Co"}'
Invoke-WebRequest `
-UseBasicParsing `
-Uri 'https://nottherealapi.com/r/<your-receiver-token>/api/data/v9.2/accounts' `
-Method POST `
-Headers @{
Authorization = 'Bearer synthetic-microsoft-dataverse-token'
Accept = 'application/json'
'OData-Version' = '4.0'
'OData-MaxVersion' = '4.0'
} `
-ContentType 'application/json' `
-Body ([Text.Encoding]::UTF8.GetBytes($body))Selected synthetic response
HTTP 204
odata-version: 4.0
odata-entityid: https://org.example.test/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)
The selected fixture's identity points to org.example.test with a fixed example row ID. It is illustrative: do not follow it expecting a persisted account or replace it with a live tenant URL for this test. HTTP header names are case-insensitive.
Client policy: retain the identity string if your workflow needs it. If an expected header is missing, flag identity as unavailable and diagnose that separately from HTTP success. Do not automatically repeat a create just to obtain its identity.
Assert separate outcomes, not an automatic sequence
Change the operation and behaviour explicitly before each test. The representation fixture is selected separately; adding a Prefer header alone does not switch the simulator. A successful create does not cause a later throttle or ETag conflict.
| Operation and behaviour | Selected wire outcome | What to assert |
|---|---|---|
Create Account: Account row createddataverse-account-created | HTTP 204 · No response body Documented | Accept success without calling json(). Read OData-EntityId when supplied; do not invent a response object. |
Create Account: Created row representationdataverse-create-representation | HTTP 201 Documented | Parse the selected JSON representation. Do not require OData-EntityId on this response. |
Update Account: Service protection throttlingdataverse-throttle | HTTP 429 · 0x80072321 · Retry-After: 30 Documented | Report failure and apply the supplied Retry-After within a bounded retry/deadline policy. Do not increase concurrency. |
Update Account: Concurrent update conflictdataverse-conflict | HTTP 412 · Representative | Report a precondition failure. Reconcile the stale write; do not treat it as a successful update or blindly repeat it. |
In real Dataverse, service-protection 429 responses include Retry-After in seconds. Use the actual header when present, cap attempts and total waiting time, and surface exhaustion to the caller. The fixture's wait and remaining-limit values are examples, not your tenant's quota.
Microsoft's optimistic-concurrency update uses If-Match and returns 412 for a stale ETag. Here, the selected 412 is representative: its message and empty error code are fixture values, and changing If-Match does not evaluate a real row version.
Request and response examples for the other selected cases
Create Account: Created row representation
Documented Synthetic illustrative example from the catalogue, not a live capture. Run only after installing your own receiver. Replace <your-receiver-token> locally; no request is sent from this page.
HTTP 201
curl / Bash request
printf '%s' '{"name":"Example Test Co"}' | \
curl -i -X POST \
'https://nottherealapi.com/r/<your-receiver-token>/api/data/v9.2/accounts' \
-H 'Authorization: Bearer synthetic-microsoft-dataverse-token' \
-H 'Accept: application/json' \
-H 'OData-Version: 4.0' \
-H 'OData-MaxVersion: 4.0' \
-H 'Prefer: return=representation' \
-H 'Content-Type: application/json' \
--data-binary @-PowerShell request
$body = '{"name":"Example Test Co"}'
Invoke-WebRequest `
-UseBasicParsing `
-Uri 'https://nottherealapi.com/r/<your-receiver-token>/api/data/v9.2/accounts' `
-Method POST `
-Headers @{
Authorization = 'Bearer synthetic-microsoft-dataverse-token'
Accept = 'application/json'
'OData-Version' = '4.0'
'OData-MaxVersion' = '4.0'
Prefer = 'return=representation'
} `
-ContentType 'application/json' `
-Body ([Text.Encoding]::UTF8.GetBytes($body))Selected synthetic response
HTTP 201
content-type: application/json
odata-version: 4.0
preference-applied: return=representation
{
"@odata.context": "https://org.example.test/api/data/v9.2/$metadata#accounts/$entity",
"@odata.etag": "W/\"536537\"",
"accountid": "00000000-0000-0000-0000-000000000001",
"name": "Example Test Co"
}Update Account: Service protection throttling
Documented Synthetic illustrative example from the catalogue, not a live capture. Run only after installing your own receiver. Replace <your-receiver-token> locally; no request is sent from this page.
HTTP 429 · 0x80072321 · Retry-After: 30
curl / Bash request
printf '%s' '{"name":"Updated Example Co"}' | \
curl -i -X PATCH \
'https://nottherealapi.com/r/<your-receiver-token>/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)' \
-H 'Authorization: Bearer synthetic-microsoft-dataverse-token' \
-H 'Accept: application/json' \
-H 'OData-Version: 4.0' \
-H 'OData-MaxVersion: 4.0' \
-H 'If-Match: *' \
-H 'Content-Type: application/json' \
--data-binary @-PowerShell request
$body = '{"name":"Updated Example Co"}'
Invoke-WebRequest `
-UseBasicParsing `
-Uri 'https://nottherealapi.com/r/<your-receiver-token>/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)' `
-Method PATCH `
-Headers @{
Authorization = 'Bearer synthetic-microsoft-dataverse-token'
Accept = 'application/json'
'OData-Version' = '4.0'
'OData-MaxVersion' = '4.0'
'If-Match' = '*'
} `
-ContentType 'application/json' `
-Body ([Text.Encoding]::UTF8.GetBytes($body))Selected synthetic response
HTTP 429
content-type: application/json
retry-after: 30
x-ms-ratelimit-burst-remaining-xrm-requests: 0
x-ms-ratelimit-time-remaining-xrm-requests: 0
odata-version: 4.0
{
"error": {
"code": "0x80072321",
"message": "Service protection API limit exceeded. Decrease request rate and retry later."
}
}Update Account: Concurrent update conflict
Representative Synthetic illustrative example from the catalogue, not a live capture. Run only after installing your own receiver. Replace <your-receiver-token> locally; no request is sent from this page.
HTTP 412 ·
curl / Bash request
printf '%s' '{"name":"Updated Example Co"}' | \
curl -i -X PATCH \
'https://nottherealapi.com/r/<your-receiver-token>/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)' \
-H 'Authorization: Bearer synthetic-microsoft-dataverse-token' \
-H 'Accept: application/json' \
-H 'OData-Version: 4.0' \
-H 'OData-MaxVersion: 4.0' \
-H 'If-Match: W/"470867"' \
-H 'Content-Type: application/json' \
--data-binary @-PowerShell request
$body = '{"name":"Updated Example Co"}'
Invoke-WebRequest `
-UseBasicParsing `
-Uri 'https://nottherealapi.com/r/<your-receiver-token>/api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)' `
-Method PATCH `
-Headers @{
Authorization = 'Bearer synthetic-microsoft-dataverse-token'
Accept = 'application/json'
'OData-Version' = '4.0'
'OData-MaxVersion' = '4.0'
'If-Match' = 'W/"470867"'
} `
-ContentType 'application/json' `
-Body ([Text.Encoding]::UTF8.GetBytes($body))Selected synthetic response
HTTP 412
content-type: application/json
odata-version: 4.0
{
"error": {
"code": "",
"message": "The row has changed since it was retrieved."
}
}A small JavaScript response boundary
This executable example accepts a Fetch API Response that you already received. It covers the bodyless success and JSON representation cases above. It performs no request, automatic retry or UI update. A non-success response stays an error, with its raw detail available for your error handler.
async function readDataverseResult(response) {
if (!response.ok) {
return {
kind: "error",
status: response.status,
retryAfter: response.headers.get("Retry-After"),
detail: await response.text()
};
}
if (response.status === 204) {
return {
kind: "no-content",
entityUrl: response.headers.get("OData-EntityId")
};
}
// For the separately selected JSON representation response.
return { kind: "representation", entity: await response.json() };
}Test a missing identity header too: entityUrl should be null, not a fabricated account URL. Invalid JSON in a supposed representation is still a parsing failure; this example does not silently turn it into success. Windows PowerShell's request sample can throw for HTTP errors: inspect that exception's response, or use the Bash curl sample to see the selected error status and body directly.
Scope, fidelity and sources
This guide targets the module's Dataverse Web API v9.2 Accounts subset. Default fixtures do not persist Accounts, negotiate Prefer or evaluate If-Match dynamically. Fixed IDs, error text, delays and quota-related headers are synthetic example values even when a response shape is labelled Documented. The opt-in bounded lifecycle is separate and requires deployment enablement; nothing here asserts that it is available or enabled.
The source links above were checked on 8 November 2026: Microsoft Learn's create, update, conditional-operation and service-protection documentation. Their semantics describe real Dataverse; the displayed commands and responses describe the selected NotTheRealAPI fixtures. The JavaScript boundary and retry/reconciliation advice are client policy, not additional simulator capabilities.
For the full test surface, see the Dataverse Accounts mock API reference. If your next bug is an HTTP-success stream that never completes, continue with OpenAI Responses partial-output and early-EOF handling.
Continue with your integration test
Read the Dataverse Accounts mock API reference for the full operation and behaviour catalogue. Compare workspace pricing and limits.
Start 7-day free trialNo card required. Your trial starts on workspace creation, with no automatic charge. Subscribing during the trial charges immediately and consumes remaining free time.
Browse all developer guides · OpenAI Responses streaming errors and early EOF

