It’d be appreciated if people stopped moving off to Discord or private messages attempting to suggest resolutions to this problem. The forums are still a public resource so in posting your solutions here, you can help others experiencing similar troubles. It’s not in good faith to hide solutions.
On the topic of actually reviewing this module, I’d like to try going top down. There isn’t much information to work off of, especially no debugging information especially if it’s supposedly been debugged to the maximum, so that already provides me with an initial disadvantage. Do you even know where the problem is isolated to and when it happens? I am almost confident that it is anything but random. Your code is very deterministic.
The defaultStats table takes up 0.4% of your allowed value size per DataStore key. While this is less than 1%, there’s still the active concern of knowing how far you go until you start pushing to save wherein loss starts occurring. It’s not exactly clear if you hit any maximums or anything.
You have quite a bit of wiggle room with limitations but for the sake of making it clear what you’re doing and divorcing unrelated stats, I highly recommend using the scope part to break off into other DataStores and refining that default portion, unless you’re confident that your data will never surpass limits and you don’t receive errors in that regard, then that’s fine.
For the if statement after the player’s data is defaulted, hopefully you’ve also made sure to review this as well as if everything here is intended. If you want to be more specific about how this if statement is being evaluated, put brackets around operand pairs. If not, then it’ll just follow default evaluation. You might not be getting the results you want there.
Up until there, that portion of the code is for you to debug. I don’t know whether your saving process are fine and these is all moot recommendations where your only problem is supposedly data being randomly lost, or if there’s further problems in your code as well up to how you fetch and apply data. It’s worth checking if data even saves at all and whether or not it pulls properly.
One case I do recommend is that you switch to UpdateAsync from SetAsync and perform a literal transformation against saved data. UpdateAsync is guaranteed to be called multiple times internally until data saves (UpdateAsync queues it), while SetAsync is a one-and-done force data to apply and if it doesn’t, then it doesn’t.
For arrays, please use ipairs, not in next
. That’s an old practice because the old VM for whatever ran that faster than ipairs. ipairs is idiomatic and the proper way to iterate through arrays. You have multiple instances where you use in next over ipairs, I’d switch.
All these things aside, they seem more like nitpicks than anything relevant towards solving the problem. That’s because there’s no information to go off of and you don’t have any provide, so actually trying to help you solve this beyond telling you to rewrite it and revise as you go is virtually the only thing that can be done.
Please try debugging further so you can have a better grasp at the problem and better information to provide. We only know as much as you do here without horribly butchering your code to even begin to find out where the problem is to make changes and see if that mitigates or removes the problem altogether.