{"record":{"id":"10629cf463d46637","repo":"microsoft/semantic-kernel","slug":"role-must-be-one-of-system-user-assistant-or-to","errorCode":null,"errorMessage":"Role must be one of: system, user, assistant or tool. {role} is an invalid role.","messagePattern":"Role must be one of: system, user, assistant or tool\\. (.+?) is an invalid role\\.","errorType":"validation","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"dotnet/src/Connectors/Connectors.MistralAI/Client/MistralChatMessage.cs","lineNumber":43,"sourceCode":"    [JsonPropertyName(\"tool_call_id\")]\n    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]\n    public string? ToolCallId { get; set; }\n\n    [JsonPropertyName(\"tool_calls\")]\n    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]\n    public IList<MistralToolCall>? ToolCalls { get; set; }\n\n    /// <summary>\n    /// Construct an instance of <see cref=\"MistralChatMessage\"/>.\n    /// </summary>\n    /// <param name=\"role\">If provided must be one of: system, user, assistant</param>\n    /// <param name=\"content\">Content of the chat message</param>\n    [JsonConstructor]\n    internal MistralChatMessage(string? role, object? content)\n    {\n        if (role is not null and not \"system\" and not \"user\" and not \"assistant\" and not \"tool\")\n        {\n            throw new System.ArgumentException($\"Role must be one of: system, user, assistant or tool. {role} is an invalid role.\", nameof(role));\n        }\n\n        this.Role = role;\n        this.Content = content;\n    }\n}\n","sourceCodeStart":25,"sourceCodeEnd":50,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/dotnet/src/Connectors/Connectors.MistralAI/Client/MistralChatMessage.cs#L25-L50","documentation":"Thrown by the MistralChatMessage JSON constructor when the supplied role is non-null but not one of the allowed values: system, user, assistant, or tool. The constructor validates the role because the Mistral chat completions API only accepts those four roles. The offending value is interpolated into the message and reported as an ArgumentException on the 'role' parameter.","triggerScenarios":"Deserializing a MistralChatMessage from JSON whose role is e.g. 'function', 'developer', 'model', 'chatbot', or any custom string; or constructing a MistralChatMessage manually with an unsupported role.","commonSituations":"Mapping chat histories from another provider (OpenAI 'function'/'tool', Gemini 'model', custom 'bot') into Mistral messages without translating the role; schema drift where a new role string appears; typos in role strings.","solutions":["Map foreign roles to Mistral roles before constructing: 'model'/'chatbot' -> 'assistant', 'function' -> 'tool', 'developer'/'system' -> 'system'.","Ensure deserialized chat history uses only system/user/assistant/tool roles.","If building messages manually, pass role as null or one of the four valid strings."],"exampleFix":"// before\nvar msg = new MistralChatMessage(role: \"model\", content: \"hi\");  // throws\n\n// after\nvar msg = new MistralChatMessage(role: \"assistant\", content: \"hi\");","handlingStrategy":"type-guard","validationCode":"static readonly HashSet<string> ValidRoles = new() { \"system\", \"user\", \"assistant\", \"tool\" };\nstatic string NormalizeRole(string? r) => r switch\n{\n    null => \"user\",\n    \"model\" or \"chatbot\" or \"bot\" => \"assistant\",\n    \"function\" => \"tool\",\n    \"developer\" => \"system\",\n    _ => ValidRoles.Contains(r) ? r : \"user\"\n};","typeGuard":"static bool IsValidMistralRole(string? r)\n    => r is null || r is \"system\" or \"user\" or \"assistant\" or \"tool\";","tryCatchPattern":"try { var msg = new MistralChatMessage(role, content); }\ncatch (ArgumentException ex) when (ex.Message.Contains(\"is an invalid role\"))\n{ logger.LogError(ex, \"Translate the role to one of system/user/assistant/tool.\"); throw; }","preventionTips":["Map foreign roles (model->assistant, function->tool) before constructing MistralChatMessage.","Validate roles with the type guard when importing chat histories.","Pass role as null to default rather than guessing."],"tags":["mistral","chat","role","validation"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}