microsoft / microsoft/kiota

Could not create error type for multiple errors with same status code

Open
#6,924 1 comment 0 reactions 0 assignees View on GitHub
Csharp type:bug type:investigation
Dominant language
C#
Stars
3.8k
Forks
333
Avg merge
16h 29m
Merged PRs (30d)
116

Description

### What are you generating using Kiota, clients or plugins?

API Client/SDK

### In what context or format are you using Kiota?

Mac executable

### Client library/SDK language

Csharp

### Describe the bug

I'm trying to generate a C# client using Kiota. If the typespec description of the client contains multiple error models with the same statusCode, then no class will be generated for that error. This separation is convenient for us, since multiple errors with the same status code can differ in fields and should be interpreted differently.

### Expected behavior

An error class was generated for a status code that describes multiple errors.

### How to reproduce

1. Build typespec project with single file:

```typespec
import "@typespec/http";
import "@typespec/rest";
import "@typespec/openapi3";

using TypeSpec.Http;

@service({
title: "Exmaple Service",
})
namespace ExampleService;

@tag("Example API")
interface ExampleApi {
@summary("Error generation example.")
@post
@route("/api/v1/example")
exampleMethod(
@body request: ExampleRequest,
): OkResponse | LogicError_NoExamplesInDatabase | LogicError_TooManyExamplesInDatabase;
}

model ExampleRequest {
Id: string;
}

model Response {
@statusCode
statusCode: Status;
}

model Body {
@body
body: Type;
}

model ErrorBody {
Message?: string;
}

@error
model LogicError is Response {
@header contentType: "application/json";
...Body;
}

model LogicError_NoExamplesInDatabase is LogicError<422>;
model LogicError_TooManyExamplesInDatabase is LogicError<422>;
```
2. Build .tsp into openapi.yaml file.
3. Prodive openapi.yml file to kiota.

### Open API description file

```yaml
openapi: 3.0.0
info:
title: Exmaple Service
version: 0.0.0
tags:
- name: Example API
paths:
/api/v1/example:
post:
operationId: ExampleApi_exampleMethod
summary: Error generation example.
parameters: []
responses:
'200':
description: The request has succeeded.
'422':
description: Client error
content:
application/json:
schema:
anyOf:
- $ref: '#/components/schemas/ErrorBody'
- $ref: '#/components/schemas/ErrorBody'
tags:
- Example API
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExampleRequest'
components:
schemas:
ErrorBody:
type: object
properties:
Message:
type: string
ExampleRequest:
type: object
required:
- Id
properties:
Id:
type: string
```

### Kiota Version

1.28.0+57130b1b1db3bc5c060498682f41e20c8ae089f2

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

_No response_

### Known Workarounds

_No response_

### Configuration

- macOs Sequoia 15.6
- arm64

### Debug output

Click to expand log
Example of execution:
```bash
kiota generate \
--language CSharp \
--openapi ./tsp-output/@typespec/openapi3/openapi.yaml \
--output ./kiota-output \
--exclude-backward-compatible \
--clean-output \
--log-level trace
trce: Kiota.Builder.KiotaBuilder[0]
configuration: {"Generation":{"ShouldGetApiManifest":false,"SkipGeneration":false,"Operation":null,"OpenAPIFilePath":"/Users/m.alonov/repos/new-engine-api/./tsp-output/@typespec/openapi3/openapi.yaml","ApiManifestPath":"/Users/m.alonov/repos/new-engine-api/apimanifest.json","OutputPath":"/Users/m.alonov/repos/new-engine-api/./kiota-output","ClientClassName":"ApiClient","TypeAccessModifier":2,"ClientNamespaceName":"ApiSdk","NamespaceNameSeparator":".","ExportPublicApi":false,"ModelsNamespaceName":"ApiSdk.models","Language":0,"PluginTypes":[],"ApiRootUrl":null,"UsesBackingStore":false,"ExcludeBackwardCompatible":true,"IncludeBackwardCompatible":false,"IncludeAdditionalData":true,"Serializers":["Microsoft.Kiota.Serialization.Json.JsonSerializationWriterFactory","Microsoft.Kiota.Serialization.Text.TextSerializationWriterFactory","Microsoft.Kiota.Serialization.Form.FormSerializationWriterFactory","Microsoft.Kiota.Serialization.Multipart.MultipartSerializationWriterFactory"],"Deserializers":["Microsoft.Kiota.Serialization.Json.JsonParseNodeFactory","Microsoft.Kiota.Serialization.Text.TextParseNodeFactory","Microsoft.Kiota.Serialization.Form.FormParseNodeFactory"],"ShouldWriteNamespaceIndices":false,"ShouldWriteBarrelsIfClassExists":false,"CleanOutput":true,"StructuredMimeTypes":["application/json","text/plain;q=0.9","application/x-www-form-urlencoded;q=0.2","multipart/form-data;q=0.1"],"IncludePatterns":[],"ExcludePatterns":[],"PatternsOverride":[],"ClearCache":false,"DisabledValidationRules":[],"IncludeKiotaValidationRules":null,"IncludePluginExtensions":null,"NoWorkspace":false,"MaxDegreeOfParallelism":-1,"IsPluginConfiguration":false,"DisableSSLValidation":false,"PluginAuthInformation":null},"Search":{"APIsGuruListUrl":"https://raw.githubusercontent.com/APIs-guru/openapi-directory/gh-pages/v2/list.json","GitHub":{"AppId":"Iv1.9ed2bcb878c90617","ApiBaseUrl":"https://api.github.com","BlockListUrl":"https://raw.githubusercontent.com/microsoft/kiota/main/resources/index-block-list.yml","AppManagement":"https://aka.ms/kiota/install/github"},"ClearCache":false},"Download":{"OutputPath":"./output/result.json","CleanOutput":false,"DisableSSLValidation":false,"ClearCache":false},"Languages":{"CSharp":{"MaturityLevel":2,"SupportExperience":0,"Dependencies":[{"Name":"Microsoft.Kiota.Abstractions","Version":"1.19.0","Type":0},{"Name":"Microsoft.Kiota.Http.HttpClientLibrary","Version":"1.19.0","Type":3},{"Name":"Microsoft.Kiota.Serialization.Form","Version":"1.19.0","Type":1},{"Name":"Microsoft.Kiota.Serialization.Json","Version":"1.19.0","Type":1},{"Name":"Microsoft.Kiota.Authentication.Azure","Version":"1.19.0","Type":2},{"Name":"Microsoft.Kiota.Serialization.Text","Version":"1.19.0","Type":1},{"Name":"Microsoft.Kiota.Serialization.Multipart","Version":"1.19.0","Type":1},{"Name":"Microsoft.Kiota.Bundle","Version":"1.19.0","Type":4}],"DependencyInstallCommand":"dotnet add package {0} --version {1}","ClientClassName":"","ClientNamespaceName":"","StructuredMimeTypes":[]},"Dart":{"MaturityLevel":0,"SupportExperience":1,"Dependencies":[{"Name":"microsoft_kiota_abstractions","Version":"0.0.2","Type":0},{"Name":"microsoft_kiota_http","Version":"0.0.2","Type":3},{"Name":"microsoft_kiota_serialization_form","Version":"0.0.2","Type":1},{"Name":"microsoft_kiota_serialization_text","Version":"0.0.2","Type":1},{"Name":"microsoft_kiota_serialization_json","Version":"0.0.2","Type":1},{"Name":"microsoft_kiota_serialization_multipart","Version":"0.0.2","Type":1},{"Name":"microsoft_kiota_bundle","Version":"0.0.2","Type":4}],"DependencyInstallCommand":"","ClientClassName":"","ClientNamespaceName":"","StructuredMimeTypes":[]},"Go":{"MaturityLevel":2,"SupportExperience":0,"Dependencies":[{"Name":"github.com/microsoft/kiota-abstractions-go","Version":"v1.9.2","Type":0},{"Name":"github.com/microsoft/kiota-http-go","Version":"v1.5.4","Type":3},{"Name":"github.com/microsoft/kiota-serialization-form-go","Version":"v1.1.2","Type":1},{"Name":"github.com/microsoft/kiota-serialization-json-go","Version":"v1.1.2","Type":1},{"Name":"github.com/microsoft/kiota-authentication-azure-go","Version":"v1.3.0","Type":2},{"Name":"github.com/microsoft/kiota-serialization-text-go","Version":"v1.1.2","Type":1},{"Name":"github.com/microsoft/kiota-serialization-multipart-go","Version":"v1.1.2","Type":1},{"Name":"github.com/microsoft/kiota-bundle-go","Version":"v1.4.2","Type":4}],"DependencyInstallCommand":"go get {0}@{1}","ClientClassName":"","ClientNamespaceName":"","StructuredMimeTypes":[]},"HTTP":{"MaturityLevel":1,"SupportExperience":0,"Dependencies":[],"DependencyInstallCommand":"","ClientClassName":"","ClientNamespaceName":"","StructuredMimeTypes":[]},"Java":{"MaturityLevel":2,"SupportExperience":0,"Dependencies":[{"Name":"com.microsoft.kiota:microsoft-kiota-abstractions","Version":"1.8.8","Type":0},{"Name":"com.microsoft.kiota:microsoft-kiota-http-okHttp","Version":"1.8.8","Type":3},{"Name":"com.microsoft.kiota:microsoft-kiota-serialization-form","Version":"1.8.8","Type":1},{"Name":"com.microsoft.kiota:microsoft-kiota-serialization-json","Version":"1.8.8","Type":1},{"Name":"com.microsoft.kiota:microsoft-kiota-authentication-azure","Version":"1.8.8","Type":2},{"Name":"com.microsoft.kiota:microsoft-kiota-serialization-text","Version":"1.8.8","Type":1},{"Name":"com.microsoft.kiota:microsoft-kiota-serialization-multipart","Version":"1.8.8","Type":1},{"Name":"com.microsoft.kiota:microsoft-kiota-bundle","Version":"1.8.8","Type":4},{"Name":"jakarta.annotation:jakarta.annotation-api","Version":"2.1.1","Type":5}],"DependencyInstallCommand":"{0}:{1}","ClientClassName":"","ClientNamespaceName":"","StructuredMimeTypes":[]},"PHP":{"MaturityLevel":2,"SupportExperience":0,"Dependencies":[{"Name":"microsoft/kiota-abstractions","Version":"1.5.0","Type":0},{"Name":"microsoft/kiota-http-guzzle","Version":"1.5.0","Type":3},{"Name":"microsoft/kiota-serialization-json","Version":"1.5.0","Type":1},{"Name":"microsoft/kiota-authentication-phpleague","Version":"1.5.0","Type":2},{"Name":"microsoft/kiota-serialization-text","Version":"1.5.0","Type":1},{"Name":"microsoft/kiota-serialization-multipart","Version":"1.5.0","Type":1},{"Name":"microsoft/kiota-serialization-form","Version":"1.5.0","Type":1},{"Name":"microsoft/kiota-bundle","Version":"1.5.0","Type":4}],"DependencyInstallCommand":"composer require {0}:{1}","ClientClassName":"","ClientNamespaceName":"","StructuredMimeTypes":[]},"Python":{"MaturityLevel":2,"SupportExperience":0,"Dependencies":[{"Name":"microsoft-kiota-abstractions","Version":"1.9.4","Type":0},{"Name":"microsoft-kiota-http","Version":"1.9.4","Type":3},{"Name":"microsoft-kiota-serialization-json","Version":"1.9.4","Type":1},{"Name":"microsoft-kiota-authentication-azure","Version":"1.9.4","Type":2},{"Name":"microsoft-kiota-serialization-text","Version":"1.9.4","Type":1},{"Name":"microsoft-kiota-serialization-form","Version":"1.9.4","Type":1},{"Name":"microsoft-kiota-serialization-multipart","Version":"1.9.4","Type":1},{"Name":"microsoft-kiota-bundle","Version":"1.9.4","Type":4}],"DependencyInstallCommand":"pip install {0}=={1}","ClientClassName":"","ClientNamespaceName":"","StructuredMimeTypes":[]},"Ruby":{"MaturityLevel":0,"SupportExperience":1,"Dependencies":[{"Name":"microsoft_kiota_abstractions","Version":"0.14.4","Type":0},{"Name":"microsoft_kiota_faraday","Version":"0.15.0","Type":3},{"Name":"microsoft_kiota_serialization_json","Version":"0.9.2","Type":1},{"Name":"microsoft_kiota_authentication_oauth","Version":"0.8.0","Type":2}],"DependencyInstallCommand":"gem install \u0022{0}\u0022 -v \u0022{1}\u0022","ClientClassName":"","ClientNamespaceName":"","StructuredMimeTypes":[]},"TypeScript":{"MaturityLevel":1,"SupportExperience":0,"Dependencies":[{"Name":"@microsoft/kiota-abstractions","Version":"1.0.0-preview.96","Type":0},{"Name":"@microsoft/kiota-http-fetchlibrary","Version":"1.0.0-preview.96","Type":3},{"Name":"@microsoft/kiota-serialization-form","Version":"1.0.0-preview.96","Type":1},{"Name":"@microsoft/kiota-serialization-json","Version":"1.0.0-preview.96","Type":1},{"Name":"@microsoft/kiota-authentication-azure","Version":"1.0.0-preview.96","Type":2},{"Name":"@microsoft/kiota-serialization-text","Version":"1.0.0-preview.96","Type":1},{"Name":"@microsoft/kiota-serialization-multipart","Version":"1.0.0-preview.96","Type":1},{"Name":"@microsoft/kiota-bundle","Version":"1.0.0-preview.96","Type":4}],"DependencyInstallCommand":"npm install {0}@{1} -SE","ClientClassName":"","ClientNamespaceName":"","StructuredMimeTypes":[]}},"Update":{"OrgName":"microsoft","RepoName":"kiota","Disabled":false}}
info: Kiota.Builder.KiotaBuilder[0]
Cleaning output directory /Users/m.alonov/repos/new-engine-api/./kiota-output
dbug: Kiota.Builder.KiotaBuilder[0]
kiota version 1.28.0
info: Kiota.Builder.KiotaBuilder[0]
loaded description from local source
trce: Kiota.Builder.KiotaBuilder[0]
2ms: Read OpenAPI file /Users/m.alonov/repos/new-engine-api/./tsp-output/@typespec/openapi3/openapi.yaml
dbug: Kiota.Builder.KiotaBuilder[0]
step 1 - reading the stream - took 00:00:00.0054992
trce: Kiota.Builder.KiotaBuilder[0]
Parsing OpenAPI file
warn: Kiota.Builder.KiotaBuilder[0]
OpenAPI warning: #/ - A servers entry (v3) or host + basePath + schemes properties (v2) was not present in the OpenAPI description. The root URL will need to be set manually with the request adapter.
trce: Kiota.Builder.KiotaBuilder[0]
54ms: Parsed OpenAPI successfully. 1 paths found.
dbug: Kiota.Builder.KiotaBuilder[0]
step 2 - parsing the document - took 00:00:00.0565405
dbug: Kiota.Builder.KiotaBuilder[0]
step 3 - updating generation configuration from kiota extension - took 00:00:00.0000486
dbug: Kiota.Builder.KiotaBuilder[0]
step 4 - filtering API paths with patterns - took 00:00:00.0041996
warn: Kiota.Builder.KiotaBuilder[0]
No server url found in the OpenAPI document. The base url will need to be set when using the client.
dbug: Kiota.Builder.KiotaBuilder[0]
step 5 - checking whether the output should be updated - took 00:00:00.0140834
trce: Kiota.Builder.KiotaBuilder[0]
1ms: Created UriSpace tree
dbug: Kiota.Builder.KiotaBuilder[0]
step 6 - create uri space - took 00:00:00.0020416
dbug: Kiota.Builder.KiotaBuilder[0]
InitializeInheritanceIndex 00:00:00.0019638
trce: Kiota.Builder.KiotaBuilder[0]
Creating class ApiClient
trce: Kiota.Builder.KiotaBuilder[0]
Creating property api of apiRequestBuilder
trce: Kiota.Builder.KiotaBuilder[0]
Creating class apiRequestBuilder
trce: Kiota.Builder.KiotaBuilder[0]
Creating property v1 of v1RequestBuilder
trce: Kiota.Builder.KiotaBuilder[0]
Creating class v1RequestBuilder
trce: Kiota.Builder.KiotaBuilder[0]
Creating property example of exampleRequestBuilder
trce: Kiota.Builder.KiotaBuilder[0]
Creating class exampleRequestBuilder
warn: Kiota.Builder.KiotaBuilder[0]
Could not create error type for 422 in ExampleApi_exampleMethod
trce: Kiota.Builder.KiotaBuilder[0]
Creating method Post of Kiota.Builder.CodeDOM.CodeType
trce: Kiota.Builder.KiotaBuilder[0]
Creating method ToPostRequestInformation of Kiota.Builder.CodeDOM.CodeType
dbug: Kiota.Builder.KiotaBuilder[0]
CreateRequestBuilderClass 00:00:00
dbug: Kiota.Builder.KiotaBuilder[0]
MapTypeDefinitions 00:00:00.0026367
info: Kiota.Builder.KiotaBuilder[0]
Removing unused model ErrorBody as it is not referenced by the client API surface
dbug: Kiota.Builder.KiotaBuilder[0]
TrimInheritedModels 00:00:00
dbug: Kiota.Builder.KiotaBuilder[0]
CleanUpInternalState 00:00:00
trce: Kiota.Builder.KiotaBuilder[0]
0ms: Created source model with 3 classes
dbug: Kiota.Builder.KiotaBuilder[0]
step 7 - create source model - took 00:00:00.0397465
dbug: Kiota.Builder.KiotaBuilder[0]
13ms: Language refinement applied
dbug: Kiota.Builder.KiotaBuilder[0]
step 8 - refine by language - took 00:00:00.0138750
trce: Kiota.Builder.KiotaBuilder[0]
17ms: Files written to /Users/m.alonov/repos/new-engine-api/./kiota-output
dbug: Kiota.Builder.KiotaBuilder[0]
step 9 - writing files - took 00:00:00.0187717
info: Kiota.Builder.KiotaBuilder[0]
loaded description from local source
trce: Kiota.Builder.KiotaBuilder[0]
0ms: Read OpenAPI file /Users/m.alonov/repos/new-engine-api/./tsp-output/@typespec/openapi3/openapi.yaml
dbug: Kiota.Builder.KiotaBuilder[0]
step 10 - writing lock file - took 00:00:00.0113110
Generation completed successfully
dbug: Kiota.Builder.KiotaBuilder[0]
Api manifest path: /Users/m.alonov/repos/new-engine-api/apimanifest.json
```

### Other information

_No response_

Contributor guide

Open the contributing guide

Research direction

Start with the `kiota generate` entry point and the provided `openapi.yaml`, reproducing the case with two errors sharing status code 422. Inspect how the generator handles the response's `anyOf` schemas, then verify that the generated C# output contains distinct error classes for both models.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, openapi
Domain
api, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.