{"record":{"id":"7752b5265caa0b6b","repo":"elsa-workflows/elsa-core","slug":"a-conversation-user-id-is-required-parameter-conversation","errorCode":null,"errorMessage":"A conversation user ID is required. (Parameter 'conversation')","messagePattern":"A conversation user ID is required\\. \\(Parameter 'conversation'\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/modules/Elsa.AI.Host/Services/InMemoryAIConversationStore.cs","lineNumber":74,"sourceCode":"\n    private static void ValidateOwnership(AIConversation existing, AIConversation conversation)\n    {\n        if (!string.Equals(NormalizeTenantId(existing.TenantId), NormalizeTenantId(conversation.TenantId), StringComparison.Ordinal))\n            throw new InvalidOperationException(\"Cannot overwrite an AI conversation that belongs to another tenant.\");\n\n        if (!string.IsNullOrWhiteSpace(existing.UserId) && !string.Equals(existing.UserId, conversation.UserId, StringComparison.Ordinal))\n            throw new InvalidOperationException(\"Cannot overwrite an AI conversation that belongs to another user.\");\n    }\n\n    private static string NormalizeTenantId(string? tenantId) => tenantId ?? \"\";\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":56,"sourceCodeEnd":77,"githubUrl":"https://github.com/elsa-workflows/elsa-core/blob/fe9217bdfa0e27f0e09e45006eb6898f616e513d/src/modules/Elsa.AI.Host/Services/InMemoryAIConversationStore.cs#L56-L77","documentation":"InMemoryAIConversationStore.Validate requires every conversation passed to SaveAsync to have a non-whitespace UserId. The user ID is used for ownership checks, so an ArgumentException naming the 'conversation' parameter is thrown when it is missing.","triggerScenarios":"Calling SaveAsync with an AIConversation whose UserId is null, empty, or whitespace.","commonSituations":"Tests constructing conversations without setting UserId; losing the current-user context so UserId defaults to null; deserializing conversations from payloads that omit the user field.","solutions":["Set conversation.UserId to the owning user's ID before saving.","Ensure user-context resolution populates UserId before store calls.","Validate the mapped object before invoking the store."],"exampleFix":"// before\nawait store.SaveAsync(new AIConversation { Id = id });\n// after\nawait store.SaveAsync(new AIConversation { Id = id, UserId = currentUserId });","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(conversation.UserId)) throw new ArgumentException(\"Conversation UserId required\");","typeGuard":"bool HasUser(AIConversation c) => !string.IsNullOrWhiteSpace(c.UserId);","tryCatchPattern":"try { await store.SaveAsync(conversation); } catch (ArgumentException ex) when (ex.ParamName == \"conversation\") { logger.LogError(ex, \"Conversation missing UserId\"); }","preventionTips":["Resolve the current user before constructing the conversation.","Reject userless conversations at the API boundary.","Add unit tests covering null/empty UserId saves."],"tags":["dotnet","validation","argument","in-memory-store"],"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"}