{"record":{"id":"7b13e8712aa20d72","repo":"microsoft/semantic-kernel","slug":"message-must-have-a-role","errorCode":null,"errorMessage":"Message must have a role.","messagePattern":"Message must have a role\\.","errorType":"exception","errorClass":"KernelException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Extensions/PromptTemplates.Handlebars/Helpers/KernelHelpers/KernelSystemHelpers.cs","lineNumber":60,"sourceCode":"    /// <param name=\"handlebarsInstance\">The <see cref=\"IHandlebars\"/>-instance.</param>\n    /// <param name=\"kernel\">Kernel instance.</param>\n    /// <param name=\"variables\">Dictionary of variables maintained by the Handlebars context.</param>\n    /// <exception cref=\"KernelException\">Exception thrown when a message does not contain a defining role.</exception>\n    private static void RegisterSystemHelpers(\n        IHandlebars handlebarsInstance,\n        Kernel kernel,\n        KernelArguments variables)\n    {\n        // TODO [@teresaqhoang]: Issue #3947 Isolate Handlebars Kernel System helpers in their own class\n        // Should also consider standardizing the naming conventions for these helpers, i.e., 'Message' instead of 'message'\n        handlebarsInstance.RegisterHelper(\"message\", static (writer, options, context, arguments) =>\n        {\n            var parameters = (IDictionary<string, object>)arguments[0];\n\n            // Verify that the message has a role\n            if (!parameters!.TryGetValue(\"role\", out object? value))\n            {\n                throw new KernelException(\"Message must have a role.\");\n            }\n\n            writer.Write($\"<{value}~>\", false);\n            options.Template(writer, context);\n            writer.Write($\"</{value}~>\", false);\n        });\n\n        handlebarsInstance.RegisterHelper(\"set\", (writer, context, arguments) =>\n        {\n            var name = string.Empty;\n            object? value = string.Empty;\n            if (arguments[0].GetType() == typeof(HashParameterDictionary))\n            {\n                // Get the parameters from the template arguments\n                var parameters = (IDictionary<string, object>)arguments[0];\n                name = (string)parameters![\"name\"];\n                value = GetArgumentValue(parameters![\"value\"], variables);\n            }","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Extensions/PromptTemplates.Handlebars/Helpers/KernelHelpers/KernelSystemHelpers.cs#L42-L78","documentation":"Thrown by the Handlebars `message` helper registered in KernelSystemHelpers when the helper's first argument (a hash/object) does not contain a `role` key. Semantic Kernel uses this helper so prompt authors can emit role-tagged chat segments inside a Handlebars template; the role is mandatory because the rendered pseudo-tags `{{role}}~` / `{{/role}}~` drive downstream chat-message parsing.","triggerScenarios":"Calling `{{message}}` without a `role`, e.g. `{{message content=\"hi\"}}` or `{{message this}}` where the object has no `role` property. Any invocation where `arguments[0]` is an IDictionary whose TryGetValue(\"role\") returns false.","commonSituations":"Authoring chat-history or system/user/assistant message blocks in a `.handlebars` prompt template and forgetting the role attribute; passing a context object that was built dynamically and the role field was conditionally omitted or mis-cased.","solutions":["Add an explicit role to the helper call, e.g. `{{message role=\"user\"}}...{{/message}}`.","Inspect the object you pass as the first argument and ensure it contains a `role` key with a non-null value.","Check for casing typos — the key must be exactly `role` (not `Role` or `userRole`)."],"exampleFix":"// before\n{{#message}}hello{{/message}}\n// after\n{{#message role=\"user\"}}hello{{/message}}","handlingStrategy":"validation","validationCode":"// Before render, ensure each message-helper call site supplies a role.\n// In code-built arguments, validate the object you pass:\nstatic bool HasRole(IDictionary<string,object> p) => p.ContainsKey(\"role\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always author `{{message role=\"...\"}}` with an explicit role attribute.","If passing a context object, assert it has a `role` key in a unit test for your templates."],"tags":["handlebars","prompt-template","configuration"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}