Return null from GetConnectorType on empty/missing schema payload#3050
Open
EricBuist wants to merge 1 commit intomicrosoft:mainfrom
Open
Return null from GetConnectorType on empty/missing schema payload#3050EricBuist wants to merge 1 commit intomicrosoft:mainfrom
EricBuist wants to merge 1 commit intomicrosoft:mainfrom
Conversation
When a connector's x-ms-dynamic-schema or x-ms-dynamic-properties sub-call
returns a 200 OK response whose body is empty or whose valuePath doesn't
resolve, ExtractFromJson yields default(JsonElement) (ValueKind ==
Undefined). GetConnectorType then forwarded that default value to
GetConnectorTypeInternal, which called je.ToString() (producing "") and
passed it to OpenApiStringReader.ReadFragment<OpenApiSchema>. Deep inside
Microsoft.OpenApi.Readers.OpenApiTextReaderReader.LoadYamlDocument,
YamlStream.Documents.First() was invoked on an empty document stream and
threw InvalidOperationException("Sequence contains no elements"). The
exception surfaced out of GetConnectorReturnTypeAsync /
GetConnectorTypeAsync as an opaque LINQ failure with no hint that the
real cause was a dynamic-schema payload that didn't contain the expected
property.
Real-world repro: Azure DevOps GetQueryResultsV2 declares its items as
x-ms-dynamic-properties with operationId=GetQueryResultWorkItemSchema and
itemValuePath=Fields. For some valid query shapes (e.g. queries whose
saved columnOptions don't map to populated Fields), the sub-call returns
200 OK with a body that has no usable value at Fields. The static 5-layer
recursion through GetConnectorTypeInternalAsync then hit LoadYamlDocument
and failed with "Sequence contains no elements" instead of simply
falling back to the static return type.
# Fix
File: src/libraries/Microsoft.PowerFx.Connectors/ConnectorFunction.cs
GetConnectorType now checks JsonElement.ValueKind against Undefined /
Null before delegating to GetConnectorTypeInternal and returns null when
the extracted element is not usable. The two async callers
(GetConnectorSuggestionsFromDynamicSchemaAsync and
GetConnectorSuggestionsFromDynamicPropertyAsync) recognize the new null
return, log a warning identifying the offending valuePath /
itemValuePath, and return null themselves. The rest of the recursion
already treats null as "no dynamic extension resolved" (see
GetConnectorTypeInternalAsync line 683), so null propagates cleanly all
the way back to GetConnectorReturnTypeAsync callers that can then fall
back to the static ReturnParameterType.
# Test
File: src/tests/Microsoft.PowerFx.Connectors.Tests.Shared/PowerPlatformConnectorTests.cs
Added four direct unit tests for GetConnectorType:
- GetConnectorType_MissingValuePath_ReturnsNull — exact AzDO repro shape
({"otherProperty":"value"} with valuePath="Fields").
- GetConnectorType_EmptyStringValue_ReturnsNull — empty StringValue.
- GetConnectorType_ValuePathResolvesToNull_ReturnsNull — {"Fields":null}.
- GetConnectorType_ValidSchemaAtValuePath_ReturnsConnectorType — happy
path, guards against the early-return swallowing valid schemas.
All four pass. Pre-existing GetConnectorType_* and dynamic-schema tests
(DVDynamicReturnType, ServiceNowOutputType_GetRecord,
ExcelOnlineAddRowV2_ItemParamHasDynamicSchema) continue to pass unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a connector's x-ms-dynamic-schema or x-ms-dynamic-properties sub-call returns a 200 OK response whose body is empty or whose valuePath doesn't resolve, ExtractFromJson yields default(JsonElement) (ValueKind == Undefined). GetConnectorType then forwarded that default value to GetConnectorTypeInternal, which called je.ToString() (producing "") and passed it to OpenApiStringReader.ReadFragment. Deep inside Microsoft.OpenApi.Readers.OpenApiTextReaderReader.LoadYamlDocument, YamlStream.Documents.First() was invoked on an empty document stream and threw InvalidOperationException("Sequence contains no elements"). The exception surfaced out of GetConnectorReturnTypeAsync / GetConnectorTypeAsync as an opaque LINQ failure with no hint that the real cause was a dynamic-schema payload that didn't contain the expected property.
Real-world repro: Azure DevOps GetQueryResultsV2 declares its items as x-ms-dynamic-properties with operationId=GetQueryResultWorkItemSchema and itemValuePath=Fields. For some valid query shapes (e.g. queries whose saved columnOptions don't map to populated Fields), the sub-call returns 200 OK with a body that has no usable value at Fields. The static 5-layer recursion through GetConnectorTypeInternalAsync then hit LoadYamlDocument and failed with "Sequence contains no elements" instead of simply falling back to the static return type.
Fix
File: src/libraries/Microsoft.PowerFx.Connectors/ConnectorFunction.cs
GetConnectorType now checks JsonElement.ValueKind against Undefined / Null before delegating to GetConnectorTypeInternal and returns null when the extracted element is not usable. The two async callers (GetConnectorSuggestionsFromDynamicSchemaAsync and GetConnectorSuggestionsFromDynamicPropertyAsync) recognize the new null return, log a warning identifying the offending valuePath / itemValuePath, and return null themselves. The rest of the recursion already treats null as "no dynamic extension resolved" (see GetConnectorTypeInternalAsync line 683), so null propagates cleanly all the way back to GetConnectorReturnTypeAsync callers that can then fall back to the static ReturnParameterType.
Test
File: src/tests/Microsoft.PowerFx.Connectors.Tests.Shared/PowerPlatformConnectorTests.cs
Added four direct unit tests for GetConnectorType:
All four pass. Pre-existing GetConnectorType_* and dynamic-schema tests (DVDynamicReturnType, ServiceNowOutputType_GetRecord, ExcelOnlineAddRowV2_ItemParamHasDynamicSchema) continue to pass unchanged.