-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Description
What happened?
When performing async database queries (such as Entity Framework Core or similar ORM operations) inside the playerConnecting event handler, the server crashes or throws exceptions, even when using deferrals.defer() and [FromSource] correctly.
The code is structured according to the official documentation:
`
private async void OnPlayerConnecting(
[FromSource] Player player, string playerName,
dynamic setKickReason, dynamic deferrals)
{
deferrals.defer();
try
{
// This causes crashes/exceptions
var ban = await BanRepo.FindActiveBanAsync(license, ip);
if (ban != null)
{
deferrals.done($"You are banned. Reason: {ban.Reason}");
return;
}
deferrals.done();
}
catch (Exception ex)
{
Logger.Error("Ban check failed", ex);
deferrals.done("Server error");
}
}
`
The database query (FindActiveBanAsync) performs a typical async operation (e.g., DbContext.Bans.Where(...).FirstOrDefaultAsync()), but this causes the server to crash or become unstable.
Expected result
According to the official playerConnecting documentation, after calling deferrals.defer(), it should be safe to perform async operations: > "Assuming you have a function called IsBanned of type Task - normally you'd do a database query here, which might take some time" The documentation example shows: if (await IsBanned(licenseIdentifier)){ deferrals.done($"You have been kicked...");} This suggests async database queries should work, but in practice they cause crashes.
Reproduction steps
-
Create a server-side C# resource with Entity Framework Core or any async database library
-
Set up a repository method that performs an async database query:
public async Task<BanData> FindActiveBanAsync(string license, string ip) { return await _dbContext.Bans .Where(b => (b.License == license || b.IpAddress == ip) && (!b.ExpiresAt.HasValue || b.ExpiresAt.Value > DateTime.UtcNow)) .FirstOrDefaultAsync(); } -
Call this method in the playerConnecting handler:
`private async void OnPlayerConnecting(
[FromSource] Player player, string playerName,
dynamic setKickReason, dynamic deferrals)
{
deferrals.defer();string license = player.Identifiers.FirstOrDefault(id => id.StartsWith("license:"));
deferrals.update("Checking ban status...");
var ban = await BanRepo.FindActiveBanAsync(license, null);
if (ban != null)
{
deferrals.done($"Banned: {ban.Reason}");
return;
}deferrals.done();
}` -
Start the server and attempt to connect
-
Server crashes or throws exceptions during the database query
Importancy
There's a workaround
Area(s)
FiveM, ScRT: C#
Specific version(s)
FiveM 25963
Additional information
No response