microsoft/semantic-kernel · error · KernelException

Max level {PayloadPropertiesHierarchyMaxDepth} of traversing

Error message

Max level {PayloadPropertiesHierarchyMaxDepth} of traversing payload properties of {operationId} operation is exceeded.

What it means

A safety guard inside GetPayloadProperties: it recursively walks OpenAPI schema Properties and throws KernelException once the recursion 'level' exceeds PayloadPropertiesHierarchyMaxDepth (constant = 10). It exists to bound traversal of deeply-nested or self-referential object schemas so the parser cannot stack-overflow or blow up memory while flattening a request body into RestApiPayloadProperty trees.

Source

Thrown at dotnet/src/Functions/Functions.OpenApi/OpenApi/OpenApiDocumentParser.cs:541

    }

    /// <summary>
    /// Returns REST API payload properties.
    /// </summary>
    /// <param name="operationId">The operation id.</param>
    /// <param name="schema">An OpenAPI document schema representing request body properties.</param>
    /// <param name="level">Current level in OpenAPI schema.</param>
    /// <returns>The REST API payload properties.</returns>
    private static List<RestApiPayloadProperty> GetPayloadProperties(string operationId, OpenApiSchema? schema, int level = 0)
    {
        if (schema is null)
        {
            return [];
        }

        if (level > PayloadPropertiesHierarchyMaxDepth)
        {
            throw new KernelException($"Max level {PayloadPropertiesHierarchyMaxDepth} of traversing payload properties of {operationId} operation is exceeded.");
        }

        var result = new List<RestApiPayloadProperty>();

        foreach (var propertyPair in schema.Properties)
        {
            var propertyName = propertyPair.Key;

            var propertySchema = propertyPair.Value;

            var property = new RestApiPayloadProperty(
                propertyName,
                propertySchema.Type,
                schema.Required.Contains(propertyName),
                GetPayloadProperties(operationId, propertySchema, level + 1),
                propertySchema.Description,
                propertySchema.Format,
                propertySchema.ToJsonSchema(),

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Refactor the offending schema to cap nesting (flatten wide DTOs, split into separate operations) so the realistic depth stays under 10.
  2. Break self-referential cycles by removing the recursive property from the request schema or marking it read-only (readOnly: true) so it is not part of the writable payload.
  3. Exclude the problematic operation via OpenApiFunctionExecutionParameters.OperationsToExclude if flattening the schema is not an option.
  4. If the depth is legitimate and you control the parser, patch PayloadPropertiesHierarchyMaxDepth in a local fork (it is a private const = 10).

Example fix

// before - recursive node, unbounded depth
//  components:
//    schemas:
//      TreeNode:
//        type: object
//        properties:
//          children:
//            type: array
//            items: { $ref: '#/components/schemas/TreeNode' }
// after - break the cycle for the writable payload
//  TreeNode:
//    type: object
//    properties:
//      name: { type: string }
//      children:
//        type: array
//        items: { $ref: '#/components/schemas/TreeNode' }
//        readOnly: true   # excluded from request payload traversal
Defensive patterns

Strategy: validation

Validate before calling

// Estimate nesting depth of a schema (treating $ref cycles as infinite).
static int MaxDepth(OpenApiSchema s, ISet<OpenApiSchema> seen = null, int depth = 0)
{
    seen ??= new HashSet<OpenApiSchema>();
    if (s is null || !seen.Add(s)) return depth;        // cycle -> stop
    int best = depth;
    foreach (var child in s.Properties.Values)
        best = Math.Max(best, MaxDepth(child, seen, depth + 1));
    seen.Remove(s);
    return best;
}
// if MaxDepth(schema) > 10 for an operation's body, expect the parser to throw.

Type guard

static bool IsWithinPayloadDepth(OpenApiSchema bodySchema, int max = 10) =>
    MaxDepth(bodySchema) <= max;

Try / catch

try
{
    var plugin = await kernel.CreatePluginFromOpenApiAsync("api", specStream);
}
catch (KernelException ex) when (ex.Message.Contains("Max level") && ex.Message.Contains("payload properties"))
{
    // flatten or de-cycle the offending schema, or exclude the operationId, then retry
}

Prevention

When it happens

Trigger: Importing an operation whose requestBody schema nests objects more than 10 levels deep, or a schema that is recursive (a property whose $ref points back to an ancestor type, e.g. a Tree/Node with children of the same type), so each recursion increments level until it passes 10.

Common situations: Specs with self-referential models (org charts, comment threads, category trees, AST nodes), deeply nested DTOs generated from database entity graphs, or circular $ref chains that OpenAPI readers expand rather than keep as references.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/048aa25dc782ad93. Report an issue: GitHub.