{"record":{"id":"5caad8574e256a94","repo":"elsa-workflows/elsa-core","slug":"a-conversation-id-is-required-parameter-conversation-5caad8","errorCode":null,"errorMessage":"A conversation ID is required. (Parameter 'conversation')","messagePattern":"A conversation ID is required\\. \\(Parameter 'conversation'\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.AI.Persistence.EFCore/Stores/EFCoreAIConversationStore.cs","lineNumber":231,"sourceCode":"\n    private static TEnum ParseEnum<TEnum>(string value, TEnum defaultValue) where TEnum : struct =>\n        Enum.TryParse<TEnum>(value, ignoreCase: true, out var result) ? result : defaultValue;\n\n    private static bool BelongsToTenant(string? storedTenantId, string? requestedTenantId) =>\n        string.Equals(NormalizeTenantId(storedTenantId), NormalizeTenantId(requestedTenantId), StringComparison.Ordinal);\n\n    private static string NormalizeTenantId(string? tenantId) => tenantId ?? \"\";\n\n    private static void ValidateUserOwnership(AIConversationRecord record, AIConversation conversation)\n    {\n        if (!string.IsNullOrWhiteSpace(record.UserId) && !string.Equals(record.UserId, conversation.UserId, StringComparison.Ordinal))\n            throw new InvalidOperationException(\"Cannot overwrite an AI conversation that belongs to another user.\");\n    }\n\n    private static void Validate(AIConversation conversation)\n    {\n        if (string.IsNullOrWhiteSpace(conversation.Id))\n            throw new ArgumentException(\"A conversation ID is required.\", nameof(conversation));\n\n        if (string.IsNullOrWhiteSpace(conversation.UserId))\n            throw new ArgumentException(\"A conversation user ID is required.\", nameof(conversation));\n    }\n}\n","sourceCodeStart":213,"sourceCodeEnd":237,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.AI.Persistence.EFCore/Stores/EFCoreAIConversationStore.cs#L213-L237","documentation":"The store's Validate method enforces required fields before persisting an AI conversation. A conversation must have a non-whitespace Id; otherwise ArgumentException with paramName 'conversation' is thrown. IDs are the primary key of the underlying EF Core record, so a missing ID cannot be persisted.","triggerScenarios":"Calling SaveAsync with an AIConversation whose Id is null, empty, or whitespace.","commonSituations":"Constructing AIConversation manually and forgetting to assign the Id; a factory or mapper returning a default-initialized object; deserializing a conversation from JSON where the Id field was absent or named differently.","solutions":["Set conversation.Id before calling SaveAsync (e.g. Guid.NewGuid().ToString()).","Check that your mapping/deserialization actually populates Id (correct JSON property name, no ignored member).","Guard with a validation check before save to fail fast in your own code."],"exampleFix":"// before\nvar conversation = new AIConversation { UserId = user };\nawait store.SaveAsync(conversation);\n// after\nvar conversation = new AIConversation { Id = Guid.NewGuid().ToString(), UserId = user };\nawait store.SaveAsync(conversation);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(conversation.Id)) throw new ArgumentException(\"A conversation ID is required before SaveAsync.\");","typeGuard":"static bool HasId(AIConversation c) => !string.IsNullOrWhiteSpace(c.Id);","tryCatchPattern":"try { await store.SaveAsync(conversation); }\ncatch (ArgumentException ex) when (ex.ParamName == \"conversation\") { /* fix caller: Id missing */ }","preventionTips":["Assign Id at construction time (Guid.NewGuid().ToString()).","Validate required fields at the API boundary before reaching the store.","Check deserialization/mapping populates Id.","Use constructors or factory methods that always generate an Id."],"tags":["ef-core","ai-conversations","validation","argument"],"backgroundTag":"missing-required-argument","analyzedSha":"fe9217bdfa0e27f0e09e45006eb6898f616e513d","analyzedAt":"2026-09-13T20:32:34.702Z","contentChangedAt":"2026-09-13T20:32:34.702Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}