Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error generating CSharp Client: The type does not contain any information #6087

Open
magahl opened this issue Feb 4, 2025 · 7 comments
Open
Labels
Csharp Pull requests that update .net code Needs: Discussion 📢 type:bug A broken experience

Comments

@magahl
Copy link

magahl commented Feb 4, 2025

What are you generating using Kiota, clients or plugins?

API Client/SDK

In what context or format are you using Kiota?

Nuget tool

Client library/SDK language

Csharp

Describe the bug

First off. I dont really know if this is a bug or not. Or if this is just not supported or a invalid schema.

But i have taken the edmx from our Dynamics 365 instance and trimmed the schema down to only include one property. After that i use Microsoft.OpenApi.OData to generate a json schema from that file. The schema seems valid when i try it on https://editor-next.swagger.io/

But when i run:

kiota generate -d c:/temp/d365_min.json -l csharp -n Dynamics -c D365Client -o c:/temp/D365/Generated --ll debug

I get an exception beacuse of an (what i believe empty type)


System.InvalidOperationException: The type does not contain any information Path: \accounts, Reference Id: Microsoft.Dynamics.CRM.crmbaseentity
   at Kiota.Builder.KiotaBuilder.CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation operation, String classNameSuffix, CodeNamespace codeNamespace, Boolean isRequestBody, String typeNameForInlineSchema, Boolean isViaDiscriminator) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1774
   at Kiota.Builder.KiotaBuilder.CreateInheritedModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation operation, String classNameSuffix, CodeNamespace codeNamespace, Boolean isRequestBody, String typeNameForInlineSchema, Boolean isViaDiscriminator) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1738
   at Kiota.Builder.KiotaBuilder.CreateInheritedModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation operation, String classNameSuffix, CodeNamespace codeNamespace, Boolean isRequestBody, String typeNameForInlineSchema, Boolean isViaDiscriminator) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1705
   at Kiota.Builder.KiotaBuilder.CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation operation, CodeElement parentElement, String suffixForInlineSchema, OpenApiResponse response, String typeNameForInlineSchema, Boolean isRequestBody, Boolean isViaDiscriminator) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1874
   at Kiota.Builder.KiotaBuilder.CreateCollectionModelDeclaration(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation operation, CodeNamespace codeNamespace, String typeNameForInlineSchema, Boolean isRequestBody) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1931
   at Kiota.Builder.KiotaBuilder.CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation operation, CodeElement parentElement, String suffixForInlineSchema, OpenApiResponse response, String typeNameForInlineSchema, Boolean isRequestBody, Boolean isViaDiscriminator) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1911
   at Kiota.Builder.KiotaBuilder.<>c__DisplayClass127_0.<CreatePropertiesForModelClass>b__0(KeyValuePair`2 x) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 2322
   at System.Linq.Enumerable.SelectEnumerableIterator`2.MoveNext()
   at System.Linq.Enumerable.OfTypeIterator[TResult](IEnumerable source)+MoveNext()
   at System.Collections.Generic.LargeArrayBuilder`1.AddRange(IEnumerable`1 items)
   at System.Collections.Generic.EnumerableHelpers.ToArray[T](IEnumerable`1 source)
   at Kiota.Builder.KiotaBuilder.CreatePropertiesForModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, CodeNamespace ns, CodeClass model) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 2314
   at Kiota.Builder.KiotaBuilder.AddModelClass(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, String declarationName, CodeNamespace currentNamespace, OpenApiOperation currentOperation, CodeClass inheritsFrom) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 2091
   at Kiota.Builder.KiotaBuilder.AddModelDeclarationIfDoesntExist(OpenApiUrlTreeNode currentNode, OpenApiOperation currentOperation, OpenApiSchema schema, String declarationName, CodeNamespace currentNamespace, CodeClass inheritsFrom) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1973
   at Kiota.Builder.KiotaBuilder.CreateModelDeclarationAndType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation operation, CodeNamespace codeNamespace, String classNameSuffix, OpenApiResponse response, String typeNameForInlineSchema, Boolean isRequestBody) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1697
   at Kiota.Builder.KiotaBuilder.CreateModelDeclarations(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation operation, CodeElement parentElement, String suffixForInlineSchema, OpenApiResponse response, String typeNameForInlineSchema, Boolean isRequestBody, Boolean isViaDiscriminator) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1904
   at Kiota.Builder.KiotaBuilder.GetExecutorMethodReturnType(OpenApiUrlTreeNode currentNode, OpenApiSchema schema, OpenApiOperation operation, CodeClass parentClass, OperationType operationType) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1279
   at Kiota.Builder.KiotaBuilder.CreateOperationMethods(OpenApiUrlTreeNode currentNode, OperationType operationType, OpenApiOperation operation, CodeClass parentClass) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 1364
   at Kiota.Builder.KiotaBuilder.CreateRequestBuilderClass(CodeNamespace currentNamespace, OpenApiUrlTreeNode currentNode, OpenApiUrlTreeNode rootNode) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 721
   at Kiota.Builder.KiotaBuilder.<>c__DisplayClass55_0.<CreateRequestBuilderClass>b__0(OpenApiUrlTreeNode childNode) in C:\Code\kiota\src\Kiota.Builder\KiotaBuilder.cs:line 736
   at System.Threading.Tasks.Parallel.<>c__DisplayClass43_0`2.<PartitionerForEachWorker>b__1(IEnumerator& partitionState, Int64 timeout, Boolean& replicationDelegateYieldedBeforeCompletion)

Expected behavior

Successfull client generation.

How to reproduce

kiota generate -d c:/temp/d365_min.json -l csharp -n Dynamics -c D365Client -o c:/temp/D365/Generated --ll debug

Open API description file

d365_min.json

Kiota Version

1.22.3+a544276a5ee9d4a7b67cc0fbd5ce2804c172fa14

Latest Kiota version known to work for scenario above?(Not required)

No response

Known Workarounds

I did run this in latest main of your repo as well.
and if i replace

throw new InvalidOperationException($"The type does not contain any information Path: {currentNode.Path}, Reference Id: {referenceId}"),

at line KiotaBuilder:1774 with

AddModelDeclarationIfDoesntExist(currentNode, operation, schema, className, shortestNamespace)

It seems to work, but I'm not sure what I'm doing here 😅

Configuration

Windows 11 24H2

x64

Debug output

Click to expand log ``` ```

Other information

No response

@magahl magahl added status:waiting-for-triage An issue that is yet to be reviewed or assigned type:bug A broken experience labels Feb 4, 2025
@github-project-automation github-project-automation bot moved this to Needs Triage 🔍 in Kiota Feb 4, 2025
@msgraph-bot msgraph-bot bot added the Csharp Pull requests that update .net code label Feb 4, 2025
@andrueastman
Copy link
Member

Thanks for raising this @magahl

I suspect that the error here is caused by the base schema being empty (only has a title and type and isn't really expected), so when the generator goes up the hierarchy and finds this empty schema.

  "components": {
    "schemas": {
      "Microsoft.Dynamics.CRM.crmbaseentity": {
        "title": "crmbaseentity",
        "type": "object"
      },
.....

Out of curiosity, when you make the code change, do you get a class called crmbaseentity generated? What does it contain?

@andrueastman andrueastman added status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close and removed status:waiting-for-triage An issue that is yet to be reviewed or assigned labels Feb 4, 2025
@magahl
Copy link
Author

magahl commented Feb 4, 2025

Yes I do get a class:

// <auto-generated/>
#pragma warning disable CS0618
using Microsoft.Kiota.Abstractions.Extensions;
using Microsoft.Kiota.Abstractions.Serialization;
using System.Collections.Generic;
using System.IO;
using System;
namespace Swegon.Crm.Dynamics.Models
{
    [global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
    #pragma warning disable CS1591
    public partial class Crmbaseentity : IAdditionalDataHolder, IParsable
    #pragma warning restore CS1591
    {
        /// <summary>Stores additional data not described in the OpenAPI description found when deserializing. Can be used for serialization as well.</summary>
        public IDictionary<string, object> AdditionalData { get; set; }
        /// <summary>
        /// Instantiates a new <see cref="global::Swegon.Crm.Dynamics.Models.Crmbaseentity"/> and sets the default values.
        /// </summary>
        public Crmbaseentity()
        {
            AdditionalData = new Dictionary<string, object>();
        }
        /// <summary>
        /// Creates a new instance of the appropriate class based on discriminator value
        /// </summary>
        /// <returns>A <see cref="global::Swegon.Crm.Dynamics.Models.Crmbaseentity"/></returns>
        /// <param name="parseNode">The parse node to use to read the discriminator value and create the object</param>
        public static global::Swegon.Crm.Dynamics.Models.Crmbaseentity CreateFromDiscriminatorValue(IParseNode parseNode)
        {
            _ = parseNode ?? throw new ArgumentNullException(nameof(parseNode));
            return new global::Swegon.Crm.Dynamics.Models.Crmbaseentity();
        }
        /// <summary>
        /// The deserialization information for the current model
        /// </summary>
        /// <returns>A IDictionary&lt;string, Action&lt;IParseNode&gt;&gt;</returns>
        public virtual IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
        {
            return new Dictionary<string, Action<IParseNode>>
            {
            };
        }
        /// <summary>
        /// Serializes information the current object
        /// </summary>
        /// <param name="writer">Serialization writer to use to serialize this model</param>
        public virtual void Serialize(ISerializationWriter writer)
        {
            _ = writer ?? throw new ArgumentNullException(nameof(writer));
            writer.WriteAdditionalData(AdditionalData);
        }
    }
}
#pragma warning restore CS0618

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs: Attention 👋 and removed status:waiting-for-author-feedback Issue that we've responded but needs author feedback to close labels Feb 4, 2025
@andrueastman
Copy link
Member

Thanks for the feedback here @magahl

@baywet Any chance you'd have some thoughts on whether it's useful to prevent the generation of "meaningless" schemas as seen in this scenario?

Arguably, as we go up the hierarchy, Kiota could try to remove/ignore the schema in the inheritance hierarchy once it's clear that the base is meaningless rather than failing.

@andrueastman andrueastman moved this from Needs Triage 🔍 to In Review 💭 in Kiota Feb 5, 2025
@andrueastman
Copy link
Member

On removing the first entry in the AllOf for the Microsoft.Dynamics.CRM.account(pointing to the meaningful schema) results in successful generation.

d365_min.json

@baywet
Copy link
Member

baywet commented Feb 6, 2025

One reason why we ignore "meaningless" schemas is because a lot of the tooling that does automatic OAS description generation from an object model produces waste with empty schemas which end up derailing kiota, or lead to a poor experience once the client is generated.

Now, one could argue that an empty type is meaningful when it's part of a type hierarchy and has a name... it's a trade off.

Let me know if you have any additional comments or questions.

@magahl
Copy link
Author

magahl commented Feb 7, 2025

The type comes from ”your” own system Dynamics365. It’s not something we really wanted. But it’s there.

https://learn.microsoft.com/en-us/power-apps/developer/data-platform/webapi/reference/crmbaseentity?view=dataverse-latest

@baywet
Copy link
Member

baywet commented Feb 10, 2025

Thank you for the additional information.

As you can imagine, Microsoft is a huge organization and sometimes misalignments happen.

@andrueastman what would you think of emitting the type, with the grand parent as the parent instead (if any) and emitting a warning instead of failing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Csharp Pull requests that update .net code Needs: Discussion 📢 type:bug A broken experience
Projects
Status: In Review 💭
Development

No branches or pull requests

3 participants