Debugging Dataverse: Master Web API Client Error Troubleshooting
When interacting with the Dataverse platform through its Web API, developers may encounter various client-side errors. Understanding the root cause of these errors and knowing the correct troubleshooting steps is crucial for efficient development and integration. This guide outlines some of the most frequently encountered client errors and provides detailed methods to diagnose and resolve them. By focusing on common misconfigurations and syntax issues, we aim to equip you with the knowledge to quickly identify problems and implement effective solutions.
Mastering Dataverse Web API client error troubleshooting involves familiarity with OData conventions, HTTP protocols, and the Dataverse metadata structure. These errors often stem from simple mistakes like typos in resource names or using the wrong HTTP method for an operation. However, they can sometimes point to more complex issues related to data formatting or request headers. Let’s explore these common errors and their resolutions.
Resource not found for the segment¶
This error indicates that the specific endpoint or resource you are trying to access via the Web API does not exist at the provided Uniform Resource Identifier (URI) path. This is a common issue when initiating requests, particularly when referencing entity sets or global actions. The error message typically pinpoints the segment of the URI that could not be resolved.
Symptoms¶
The client request attempts to access a resource using a specific name in the URI segment.
Request
GET [Organization URI]/api/data/v9.2/Account HTTP/1.1
The Dataverse Web API responds with an HTTP 404 Not Found status code. The response body includes a specific error code and message detailing that the resource segment was not found.
Response
HTTP/1.1 404 Not Found
{
"error": {
"code": "0x8006088a",
"message": "Resource not found for the segment 'Account'."
}
}
Cause¶
The primary cause of this error is using an incorrect name for the resource segment in the request URI. Dataverse Web API endpoints, following OData standards, are case sensitive for entity set names, functions, and actions. A mismatch in capitalization or spelling will result in the resource not being found. For instance, requesting /accounts is correct for the Account entity set, while /Account will fail.
Furthermore, if the resource is a custom action defined within Dataverse as a process, this error can occur if the custom process action is not active. Only active actions are exposed and callable via the Web API endpoint. An inactive process is essentially unavailable to external requests.
How to avoid¶
To prevent “Resource not found for the segment” errors, ensure the resource name used in the URI precisely matches the name defined in the Dataverse service metadata. For entity types, the collective noun form (plural) is used as the entity set name in the URI, and these are typically lowercase. For example, the Account entity type corresponds to the accounts entity set.
Consult the Dataverse Web API Service Document. This document is available at [Organization URI]/api/data/v9.2/ and lists all available top-level entity sets that can be queried. Verify the exact, case-sensitive name of the entity set you intend to access from this document.
For functions and actions, the definitive source for names is the CSDL $metadata document, accessible at [Organization URI]/api/data/v9.2/$metadata. This document provides a comprehensive schema of the Dataverse API, including the names and signatures of all exposed functions and actions. Search this document for the specific function or action name you are trying to invoke and confirm its exact name and required parameters.
If the resource you are trying to call is a custom process action, navigate to the Dataverse maker portal or solution explorer where the action is defined. Verify that the status of the custom action is set to ‘Activated’. If it’s inactive, activate it and then attempt the Web API request again. Remember that changes to custom processes might take a few moments to become fully effective.
Could not find a property named ‘{property name}’ on type ‘Microsoft.Dynamics.CRM.{entity name}’¶
This error indicates that a property name specified in the request payload or URI (commonly in $select, $filter, or $orderby queries) does not match any known property for the target entity type. Similar to resource names, property names in the Dataverse Web API are case-sensitive, and a mismatch in capitalization is a frequent cause.
Symptoms¶
A client request includes a property name that Dataverse does not recognize for the entity being targeted. This usually happens in query options or the body of requests like PATCH or POST.
Request
GET [Organization URI]/api/data/v9.2/accounts?$select=Name HTTP/1.1
The server responds with an HTTP 400 Bad Request status, indicating that the request syntax or content is invalid. The error details explicitly state that the property name could not be found on the specified entity type.
Response
HTTP/1.1 400 Bad Request
{
"error": {
"code": "0x0",
"message": "Could not find a property named 'Name' on type 'Microsoft.Dynamics.CRM.account'."
}
}
Cause¶
The root cause is incorrect spelling or capitalization of a property name. Dataverse properties have specific logical names and schema names, which are case-sensitive when used in Web API requests. In the example symptom, the property name Name was used, but the correct logical name for the primary name field on the account entity is name. OData services strictly adhere to the defined schema names from the metadata.
This error confirms that the OData service did not find a property matching the exact string ‘Name’ on the ‘Microsoft.Dynamics.CRM.account’ type as defined in its metadata. While the entity set name (accounts) was correct (lowercase), the property name (Name) was not. This highlights the importance of using the exact, case-sensitive schema names.
How to avoid¶
To avoid this error, always verify the correct, case-sensitive name of the property you intend to use. The authoritative source for property names is the CSDL $metadata document, accessible at [Organization URI]/api/data/v9.2/$metadata. Navigate through the XML structure of the metadata document to find the definition for the specific entity type (e.g., EntityType Name="account"). Within the entity type definition, look for Property elements.
Each Property element will list the Name attribute, which represents the schema name used in Web API requests. For the account entity, you would find <Property Name="name" Type="Edm.String" MaxLength="160" unicode="true" />. This shows that the correct name is name, not Name. Always cross-reference the property name you are using against this metadata.
Understand that the logical name of a column in Dataverse (which you might see in the UI or SDK code) typically matches the schema name, but it’s crucial to confirm this mapping against the $metadata document. The CSDL $metadata document provides the precise names that the OData endpoint expects. Pay close attention to case, as this is the most common discrepancy leading to this specific error. Using development tools that can browse or validate against OData metadata can also help catch these errors early.
No HTTP resource was found that matches the request URI¶
This error occurs when the Dataverse Web API endpoint is unable to route the incoming HTTP request to a specific OData resource handler. While it might seem similar to “Resource not found for the segment,” this error often specifically points to an issue with the combination of the request URI and the HTTP method used, rather than just the resource name itself.
Symptoms¶
A request is sent to a valid Dataverse Web API endpoint path, but the server cannot find a configured handler for the specific HTTP method used for that path.
Request
POST [Organization URI]/api/data/v9.2/WhoAmI
The server responds with an HTTP 404 Not Found status. The error message typically indicates that no HTTP resource matching the request URI was found, without specifying a segment like the previous error.
Response
HTTP/1.1 404 Not Found
{
"error": {
"code": "",
"message": "No HTTP resource was found that matches the request URI '[Organization URI]/api/data/v9.2/WhoAmI'."
}
}
Cause¶
The cause is sending an HTTP request with a method (like POST, PUT, PATCH, DELETE) that is not supported or expected by the specific resource identified by the URI. OData resources, including functions and actions, are designed to respond only to certain HTTP methods based on their definition. For example, OData functions are typically invoked using the GET method because they are designed to perform read-only operations and return data. OData actions, which can have side effects (like creating, updating, or deleting data) or perform complex operations, are typically invoked using the POST method.
In the symptom example, the WhoAmI resource corresponds to an OData function. Functions are intended for retrieving data and should be called using GET. The request attempted to use POST, which is not supported for this specific function endpoint. Therefore, the Dataverse endpoint couldn’t find a “POST handler” for the /WhoAmI URI, resulting in the “No HTTP resource found” error.
How to avoid¶
To prevent this error, you must use the correct HTTP method appropriate for the type of OData operation you are performing. This requires understanding whether the target resource is an entity set, a function, or an action, and what standard HTTP methods are associated with each in OData.
- Entity Sets:
GET /entityset: Retrieve multiple entities.POST /entityset: Create a new entity.
- Individual Entities:
GET /entityset(id): Retrieve a specific entity.PATCH /entityset(id): Update (partially) a specific entity.PUT /entityset(id): Replace a specific entity (less common for full entity replacement, often used for property updates).DELETE /entityset(id): Delete a specific entity.
- Functions:
- Typically invoked with
GET. Functions represent operations that return data and usually have no side effects. TheWhoAmIfunction is a prime example. Parameters are typically passed in the URI query string.
- Typically invoked with
- Actions:
- Typically invoked with
POST. Actions represent operations that can have side effects and may return data or a status. Parameters are usually passed in the request body.
- Typically invoked with
Consult the CSDL $metadata document ([Organization URI]/api/data/v9.2/$metadata) to confirm whether a resource is defined as a FunctionImport or ActionImport. This will tell you whether it’s a function (usually GET) or an action (usually POST). For custom actions created in Dataverse, they are always invoked using POST. Always refer to the official documentation for specific system-defined functions and actions if their behavior or required method isn’t immediately clear from the metadata.
Invalid property {property name} was found in entity ‘Microsoft.Dynamics.CRM.{entity name}’¶
This error is very similar to the “Could not find a property named…” error but often appears in a slightly different context, specifically when submitting data in a request body (like during create or update operations). It reinforces the strict requirement for case-sensitive property names when serializing JSON payloads for Dataverse.
Symptoms¶
A request is sent to create or update an entity record, and the request body contains a JSON payload that includes a property name that does not match the expected schema name for the target entity type.
Request
POST [Organization URI]/api/data/v9.2/accounts HTTP/1.1
{
"Name": "Account name"
}
The server responds with HTTP 400 Bad Request. The error message indicates an invalid property was found during validation of the input parameters, specifically within the context of the target entity type. The inner exception might provide further OData-specific details about why the property was rejected.
Response
```lang- ελληνικά
HTTP/1.1 400 Bad Request
{
“error”: {
“code”: “0x0”,
“message”: “An error occurred while validating input parameters:
Microsoft.Crm.CrmException: Invalid property ‘Name’ was found in entity ‘Microsoft.Dynamics.CRM.account’.
—> Microsoft.OData.ODataException: Does not support untyped value in non-open type.
}
}
### Cause
The fundamental cause is identical to the "Could not find a property" error: a case mismatch in the property name. When sending a JSON payload to create (POST) or update (PATCH/PUT) an entity, the JSON key for each property must exactly match the property's schema name as defined in the Dataverse metadata, including capitalization.
In the symptom example, the request body used `"Name": "Account name"`. As discussed earlier, the correct schema name for the primary name field of the account entity is lowercase `name`. The OData deserializer on the server side received `"Name"` and, being case-sensitive, could not map it to the expected `name` property on the `account` entity type. The error message confirms that `Invalid property 'Name'` was found during the input validation process.
### How to avoid
The resolution mirrors the previous property name error: rigorously verify the exact, case-sensitive schema name for every property included in your request body. The CSDL $metadata document (`[Organization URI]/api/data/v9.2/$metadata`) is the definitive source. Locate the `EntityType` definition for the relevant entity (e.g., `account`) and find the `Property` elements within it. Use the `Name` attribute value from the `Property` element directly as the key in your JSON payload.
For instance, for the account name, the metadata shows `<Property Name="name" ...>`. Therefore, your JSON payload must use `"name": "Account name"`. Any variation in capitalization will result in this error. Developing against the CSDL metadata or using client libraries that are built based on the metadata can help ensure correctness. Always double-check property names, especially when manually constructing JSON payloads for create or update operations.
## Error identified in Payload provided by the user for Entity '{entity name}'
This is a more general error message indicating a problem with the structure or content of the request payload itself, specifically in relation to the OData format and the expected entity structure. This error often has a significant InnerException that provides more specific details about the underlying issue. We will examine two common inner exceptions associated with this message.
This error suggests that the server successfully received the request and identified the target entity, but failed to process the data within the request body according to OData/Dataverse rules. The issue is typically with how relationships are specified or how the data stream is formatted.
### InnerException : Microsoft.OData.ODataException: An undeclared property [...] was found in the payload
This specific inner exception usually occurs when attempting to link records using navigation properties, and the name used for the navigation property is incorrect or improperly formatted within the OData binding syntax.
#### Symptoms
A request, typically a POST (create) or PATCH (update), includes an attempt to set a lookup value using the `@odata.bind` annotation, but the name preceding `@odata.bind` does not correspond to a valid single-valued navigation property for the entity type.
**Request**
```lang-http
POST [Organization URI]/api/data/v9.2/contacts HTTP/1.1
{
"firstname":"test",
"lastname":"contact",
"parentcustomerid@odata.bind": "accounts(a779956b-d748-ed11-bb44-6045bd01152a)"
}
The response is HTTP 400 Bad Request. The main error message is the generic “Error identified in Payload,” but the InnerException clearly states that an “undeclared property” was found, specifically one with only property annotations but no value, which points to an issue with an OData binding annotation.
Response
HTTP/1.1 400 Bad Request
{
"error": {
"code": "0x80048d19",
"message": "Error identified in Payload provided by the user for Entity :'contacts' ---->
InnerException : Microsoft.OData.ODataException: An undeclared property 'parentcustomerid'
which only has property annotations in the payload but no property value was found in the payload.
In OData, only declared navigation properties and declared named streams can be represented as
properties without values <truncated for brevity>".
}
}
Cause¶
The error arises because the name used before @odata.bind is the logical name of the lookup column (parentcustomerid) and not the name of the corresponding single-valued navigation property. In OData, relationships between entities are represented by navigation properties, not the logical names of the lookup fields. Dataverse exposes these relationships via navigation properties in its OData endpoint.
Lookup columns in Dataverse, especially multi-table lookups like customer (which can link to Account or Contact), have corresponding navigation properties that might have different names than the logical column name. For the parentcustomerid lookup on the contact entity, there are two potential relationships (one to Account, one to Contact), exposed as different single-valued navigation properties. The correct navigation property name for linking a contact to its parent account is parentcustomerid_account, not parentcustomerid.
How to avoid¶
Always use the correct, case-sensitive single-valued navigation property name when using the @odata.bind annotation to set lookup values. The logical name of the lookup column itself is not the correct identifier in this context.
Consult the CSDL $metadata document ([Organization URI]/api/data/v9.2/$metadata) to find the correct navigation property names. Locate the EntityType definition for the entity you are working with (e.g., contact). Look for NavigationProperty elements with a Type attribute that refers to a single entity type (e.g., Type="Microsoft.Dynamics.CRM.account" or Type="Microsoft.Dynamics.CRM.contact"). The Name attribute of this NavigationProperty element is what you should use before @odata.bind.
For a contact entity linking to a parent account via the parentcustomerid lookup, you would find a NavigationProperty like <NavigationProperty Name="parentcustomerid_account" Type="Microsoft.Dynamics.CRM.account" Nullable="false" Partner="contact_customer_accounts" />. This confirms parentcustomerid_account is the correct navigation property name.
Here’s a quick way to visualize the difference:
| Purpose | Identifier Type | Example for Contact’s Parent Lookup | Usage Context |
|---|---|---|---|
| Column identification | Logical Column Name | parentcustomerid |
SDK code, form editor, views |
| Relationship Navigation | Single-valued Nav Prop | parentcustomerid_account |
OData @odata.bind, expanding lookups |
Using the correct navigation property name, the request body should be:
{
"firstname":"test",
"lastname":"contact",
"parentcustomerid_account@odata.bind": "/accounts(a779956b-d748-ed11-bb44-6045bd01152a)"
}
Note the change from parentcustomerid@odata.bind to parentcustomerid_account@odata.bind. Also, include a leading / in the @odata.bind value, which is standard OData practice for absolute URIs relative to the service root.
InnerException : System.ArgumentException: Stream was not readable¶
This specific inner exception is commonly associated with errors encountered when executing batch operations using the $batch endpoint. It indicates a problem with how the multipart HTTP request body is formatted, specifically related to line endings or overall structure that prevents the server from correctly parsing the stream of data.
Symptoms¶
When sending a POST request to the $batch endpoint ([Organization URI]/api/data/v9.2/$batch) with a multipart request body containing multiple OData operations, the request fails with an HTTP 400 Bad Request. The main error is “Error identified in Payload provided by the user,” and the inner exception is System.ArgumentException: Stream was not readable. The stack trace often involves stream reading or deserialization classes.
Response snippet showing the error:
--batchresponse_5bd81edb-2ef9-4269-85c3-4623981e6c6e
Content-Type: application/http
Content-Transfer-Encoding: binary
HTTP/1.1 400 Bad Request
REQ_ID: ...
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0
{"error":{... "message":"Error identified in Payload provided by the user for Entity :'accounts',
...----> InnerException : System.ArgumentException: Stream was not readable.\r\n
at System.IO.StreamReader..ctor(Stream stream, ...)"}}
--batchresponse_5bd81edb-2ef9-4269-85c3-4623981e6c6e--
Cause¶
The most common cause of this error is the use of incorrect line endings within the batch request body. According to HTTP/1.1 and the multipart MIME standard used for OData batch requests, line endings must be represented by Carriage Return followed by Line Feed (CRLF), which is \r\n. If line endings use only Line Feed (LF, \n) (common in Unix-like systems) or only Carriage Return (CR, \r), the server’s OData deserializer might fail to correctly parse the boundaries and headers within the multipart stream.
The error message “Stream was not readable” occurs because the parser expects CRLF to delimit lines and headers within each part of the batch request. If it encounters unexpected line endings, it might fail to read the stream correctly, interpreting the data stream as malformed or incomplete. This is particularly critical for the boundary delimiters and the headers of individual requests within the batch.
The batch request structure relies on precise line endings:
--batch_<boundary_string>CRLF <-- Start Boundary
Content-Type: application/httpCRLF <-- Part Header
Content-Transfer-Encoding: binaryCRLF <-- Part Header
CRLF <-- Header/Body Separator
<HTTP request for the operation>CRLF <-- Request Lines
CRLF <-- Request Body Separator (if body exists)
<Request body JSON>CRLF <-- Request Body
--batch_<boundary_string>--CRLF <-- End Boundary
If any of the CRLF sequences are just LF or CR, parsing can fail. This is especially problematic at the very end of the batch request body. The final boundary marker must be followed by CRLF.
A simple diagram of a batch structure:
mermaid
graph TD
A[Batch Request Body] --> B{Boundary CRLF};
B --> C{Part Headers CRLF};
C --> D{Empty Line CRLF};
D --> E{Request CRLF};
E --> F{Optional Body CRLF};
F --> G{Boundary CRLF};
G --> H{... Repeat for more parts ...};
H --> I{End Boundary -- CRLF};
This visual emphasizes the necessity of CRLF after each significant line in the batch structure, including the closing boundary.
How to avoid¶
Ensure that all line endings in your $batch request body are CRLF (\r\n). This includes the line endings after the starting boundary, the headers within each request part, the empty line separating headers from the body within each part, each line of the HTTP request within a part, and critically, the line ending after the final batch boundary marker (--batch_<boundary_string>--).
When programmatically constructing batch requests, explicitly use \r\n for line breaks rather than relying on default system line endings. If you are manually creating the request body, use an editor capable of showing line endings (like Notepad++ with “Show All Characters”) to verify that CRLF is used everywhere.
Some client libraries or network stacks might handle line endings translation, but it’s safest to control this explicitly when dealing with multipart requests like OData batch. If, for some reason, you cannot guarantee CRLF for every line ending, the OData batch specification allows for non-CRLF line endings if followed by two line breaks. However, the standard and most reliable method for Dataverse is strict CRLF adherence. Always double-check the structure and line endings, especially the final boundary line ending.
Error identified on the ‘odata.include-annotations’ value inside the ‘Prefer’ header¶
This error occurs when the Prefer request header, specifically the odata.include-annotations preference, contains a value that is syntactically incorrect or improperly formatted according to OData or HTTP header standards.
Symptoms¶
A client sends a request (POST, PATCH, PUT, or GET) that includes a Prefer header with the odata.include-annotations preference. The value provided for this preference is malformed, preventing the server from correctly parsing the header.
Request
POST [Organization URI]/api/data/v9.2/contacts HTTP/1.1
Prefer: odata.include-annotations=\"*\"
{
"firstname":"test",
"lastname":"contact"
}
The server responds with an HTTP 400 Bad Request. The error message specifically calls out the Prefer header and the odata.include-annotations value as the source of the problem, often providing details about the parsing failure, including the position where the error was detected.
Response
HTTP/1.1 400 Bad Request
{
"Message": "Error identified on the 'odata.include-annotations' value inside the 'Prefer' header.
Refer to the following link for more details: https://go.microsoft.com/fwlink/?linkid=2300109.
See exception message for more details 'An error occurred when parsing the HTTP header 'Prefer'. The header value 'odata.include-annotations=\\\"*\\\\\\\"' is incorrect at position '26' because the escape character '\\\\' is not inside a quoted-string.'.",
"ErrorCode": "0x80097303"
}
Cause¶
The cause is malformed syntax within the value of the odata.include-annotations preference in the Prefer header. HTTP header values have specific formatting rules. If a value contains special characters that need escaping, the escaping method must adhere to HTTP standards.
In the symptom example, the value was specified as \"*\". The backslashes (\) before the double quotes are incorrect escaping for an HTTP header value. HTTP headers often use quoted strings to contain values that might otherwise be misinterpreted, but the contents within the quotes typically do not require backslash escaping for simple characters like *. The error message “the escape character ‘\’ is not inside a quoted-string” is a bit misleading; it highlights that the backslash isn’t valid in that context according to the parser’s rules for the expected value format. The correct way to include literal double quotes in a quoted string within an HTTP header value depends on the specific context, but often it involves doubling the quote ("") or simply not escaping if the characters are allowed within a quoted string. For odata.include-annotations, the value "*" needs to be a quoted string.
Historically, Dataverse might have been more lenient with validating the Prefer header on certain HTTP methods (POST, PATCH, PUT), but this has been updated to enforce stricter validation across all methods (GET, POST, PATCH, PUT). This increased validation surfaced the underlying formatting issue. This particular change was noted to begin deployment in January 2025.
How to avoid¶
Ensure the value provided for odata.include-annotations in the Prefer header follows the correct OData and HTTP header syntax. The value should be a quoted string containing a comma-separated list of annotation names or wildcards (*). The standard way to represent this value when you want all annotations is "*".
The Prefer header format for odata.include-annotations should look like this:
Prefer: odata.include-annotations="*"
Or, if you want specific annotations:
Prefer: odata.include-annotations="OData.Community.Display.V1.FormattedValue,Microsoft.Dynamics.CRM.associatednavigationproperty"
Notice that the value is enclosed in standard double quotes ("), and no backslash escaping is needed for the asterisk or the dots/colons/dashes in annotation names. If you needed to include a literal double quote within the annotation name itself (which is highly unlikely for standard OData or CRM annotations), the correct escaping within an HTTP quoted string would typically be to double the quote (""). However, for common use cases like "*" or listing standard annotations, simple double quotes around the value are sufficient.
Review the official Dataverse Web API documentation on Prefer headers to understand the expected format and supported preference values. Adhering to the documented syntax will prevent parsing errors like this.
See also¶
Understanding these common client errors is a significant step towards successful integration with the Dataverse Web API. By paying close attention to case sensitivity in names, using the correct HTTP methods, validating payload structures against metadata, and correctly formatting headers, you can avoid many frustrating debugging sessions. Always consult the CSDL $metadata document as the ultimate source of truth for resource, property, and navigation property names, as well as the definitions of functions and actions. Leveraging tools that help browse or generate code based on the OData metadata can significantly reduce the chances of introducing these syntax errors.
Debugging is an essential part of development. When you encounter an error, systematically check the request URI, HTTP method, request headers, and request body against the expected format and names defined in the Dataverse metadata. The error message itself, particularly any inner exceptions, often provides crucial clues about where the problem lies.
What are some other Dataverse Web API errors you’ve encountered and found challenging to debug? Share your experiences or ask questions in the comments below! Let’s learn from each other.
Post a Comment