{"record":{"id":"612607e3ad0ca053","repo":"microsoft/semantic-kernel","slug":"failed-to-deserialize-workflow","errorCode":null,"errorMessage":"Failed to deserialize workflow.","messagePattern":"Failed to deserialize workflow\\.","errorType":"exception","errorClass":"KernelException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Experimental/Process.Core/Workflow/WorkflowBuilder.cs","lineNumber":664,"sourceCode":"    }\n\n    #endregion\n\n    private Dictionary<string, JsonNode> ExtractNodeInputs(string nodeId)\n    {\n        var input = new StringReader(this._yaml ?? \"\");\n        var yamlStream = new YamlStream();\n        yamlStream.Load(input);\n\n        var rootNode = yamlStream.Documents[0].RootNode;\n        var agentsNode = rootNode[\"nodes\"] as YamlSequenceNode;\n        var node = agentsNode?.Children\n            .OfType<YamlMappingNode>()\n            .FirstOrDefault(node => node[\"id\"]?.ToString() == nodeId);\n\n        if (node is null || !node.Children.TryGetValue(\"inputs\", out YamlNode? inputs) || input is null || inputs is not YamlMappingNode inputMap)\n        {\n            throw new KernelException(\"Failed to deserialize workflow.\");\n        }\n\n        // This dance to convert the YamlMappingNode to a string and then back to a JsonSchema is rather inefficient, need to find a better option.\n        // Serialize the YamlMappingNode to a Yaml string\n        var serializer = new SerializerBuilder().Build();\n        string rawYaml = serializer.Serialize(inputMap);\n\n        // Deserialize the Yaml string to an object\n        var deserializer = new DeserializerBuilder().WithNamingConvention(UnderscoredNamingConvention.Instance).Build();\n        var yamlObject = deserializer.Deserialize(rawYaml);\n\n        // Serialize the object to a JSON string\n        var jsonSchema = JsonSerializer.Serialize(yamlObject);\n        var jsonNode = JsonNode.Parse(jsonSchema) ?? throw new KernelException(\"Failed to parse schema.\");\n\n        var inputsDictionary = inputMap.Select(inputMap => new KeyValuePair<string, JsonNode>(inputMap.Key.ToString(), jsonNode))\n            .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);\n","sourceCodeStart":646,"sourceCodeEnd":682,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Experimental/Process.Core/Workflow/WorkflowBuilder.cs#L646-L682","documentation":"Thrown by `ExtractNodeInputs` when the requested `nodeId` cannot be found in the workflow YAML's `nodes` list, or when the matched node has no `inputs` mapping (or the inputs node is not a YAML mapping). The builder cannot proceed to extract input schemas without an inputs map. It is a KernelException.","triggerScenarios":"Call `ExtractNodeInputs(nodeId)` with an id that is not present under `nodes`; the node exists but omits the `inputs` key; the `inputs` value is a scalar/sequence instead of a mapping; the YAML document is empty or malformed so `Documents[0]` yields no root.","commonSituations":"Looking up inputs for a node that only has agent metadata; authoring a node without an `inputs:` block; whitespace/indentation errors making `inputs` parse as a sibling key; referencing a node id with different casing.","solutions":["Verify the node id exists under `nodes` and has an `inputs:` mapping (indented correctly under the node).","Ensure `inputs` is a YAML map of key/value pairs, not a list or scalar.","Confirm the YAML document is non-empty and well-formed (parse it standalone first)."],"exampleFix":"# before\nnodes:\n  - id: agent1\n    type: myAgent\n# after\nnodes:\n  - id: agent1\n    type: myAgent\n    inputs:\n      message: \"hello\"","handlingStrategy":"validation","validationCode":"var node = workflow.Nodes.FirstOrDefault(n => string.Equals(n.Id, nodeId, StringComparison.Ordinal));\nif (node is null)\n    throw new InvalidOperationException($\"Node '{nodeId}' not found in workflow.\");\nif (node.Inputs is null || node.Inputs.Count == 0)\n    throw new InvalidOperationException($\"Node '{nodeId}' has no inputs mapping.\");\n// then call ExtractNodeInputs(nodeId)","typeGuard":"bool NodeHasInputs(Workflow wf, string nodeId) =>\n    wf.Nodes.FirstOrDefault(n => string.Equals(n.Id, nodeId, StringComparison.Ordinal))?.Inputs is { Count: > 0 };","tryCatchPattern":"try { var inputs = builder.ExtractNodeInputs(nodeId); }\ncatch (KernelException ex) when (ex.Message.Contains(\"Failed to deserialize workflow\"))\n{ _logger.LogError(ex, \"Node '{NodeId}' missing or has no inputs mapping.\", nodeId); throw; }","preventionTips":["Ensure every node that needs inputs has an inputs: mapping in YAML.","Validate YAML indentation so inputs is a child of the node, not a sibling."],"tags":["workflow","process-framework","yaml","deserialization","validation"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}