{"record":{"id":"aac6e5cc7c415424","repo":"dotnet/orleans","slug":"you-have-already-created-5-polls-which-is-enough","errorCode":null,"errorMessage":"You have already created 5 polls, which is enough for anybody.","messagePattern":"You have already created 5 polls, which is enough for anybody\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"samples/Voting/Grains/UserAgentGrain.cs","lineNumber":48,"sourceCode":"\n        // Get a reference to the poll grain\n        var pollGrain = _grainFactory.GetGrain<IPollGrain>(pollId);\n\n        // Get the current poll results\n        var results = await pollGrain.GetCurrentResults();\n\n        // Return the results as well as whether we've voted in the poll or not\n        return (Results: results, Voted: _votedPolls.Contains(pollId));\n    }\n\n    public async Task<string> CreatePoll(PollState initialState)\n    {\n        Throttle();\n\n        // Limit the number of polls any one user can make\n        if (_myPolls.Count >= 5)\n        {\n            throw new InvalidOperationException(\"You have already created 5 polls, which is enough for anybody.\");\n        }\n\n        // Generate a new id and get a reference to the PollGrain with that id\n        var pollId = Guid.NewGuid().ToString(\"N\")[..6];\n        var pollGrain = _grainFactory.GetGrain<IPollGrain>(pollId);\n\n        // Create the poll. We could avoid collisions here by making this return an error if a poll\n        // with that id already exists.\n        await pollGrain.CreatePoll(initialState);\n\n        _myPolls.Add(pollId);\n        return pollId;\n    }\n\n    public async Task<PollState> AddVote(string pollId, int optionId)\n    {\n        Throttle();\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/dotnet/orleans/blob/fca799fa70ecb6ad975224271703ca43221f58de/samples/Voting/Grains/UserAgentGrain.cs#L30-L66","documentation":"Thrown by Voting UserAgentGrain.CreatePoll when the user has already created 5 polls (_myPolls.Count >= 5). It enforces a per-user quota, a deliberate limit (the message is a deliberate Quora-style joke 'enough for anybody').","triggerScenarios":"A user (one grain key per user) calls CreatePoll a sixth time; _myPolls is a per-activation set that grows by one each successful create.","commonSituations":"A test loop creating many polls under the same user id; a UI bug that double-submits; legitimately needing more than five polls.","solutions":["Use a different user grain key (new user) once the quota is reached.","Raise or remove the `>= 5` cap if your fork needs more polls.","Catch InvalidOperationException and tell the user they have reached the limit."],"exampleFix":"// before\nif (_myPolls.Count >= 5) throw new InvalidOperationException(\"...\");\n\n// after: configurable quota\nif (_myPolls.Count >= MaxPollsPerUser) throw new InvalidOperationException(\"...\");","handlingStrategy":"try-catch","validationCode":"// Track polls created per user on the client and stop before the limit\nif (createdPolls >= 5) { ShowMessage(\"Poll limit reached.\"); return; }","typeGuard":"null","tryCatchPattern":"try { await user.CreatePoll(state); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"5 polls\"))\n{ /* inform user they hit the quota */ }","preventionTips":["Treat five polls per user as a hard cap; use a new user id beyond it.","Raise the constant in your fork if more polls are needed.","Catch InvalidOperationException to surface the limit gracefully."],"tags":["voting","quota","validation","sample"],"backgroundTag":null,"analyzedSha":"fca799fa70ecb6ad975224271703ca43221f58de","analyzedAt":"2026-08-13T19:55:57.938Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}