Kareadita/Kavita · error · KavitaException
client-device-doesnt-exist
Error message
client-device-doesnt-exist
What it means
Thrown by DeleteDeviceAsync when the specified deviceId is not found for the given userId. The repository call GetClientDeviceById(deviceId, userId) scopes the lookup to the user, so this fires whether the device ID is wrong or belongs to another user. It is a KavitaException (UI-facing, not Sentry).
Source
Thrown at Kavita.Services/ClientDeviceService.cs:113
return false;
}
device.FriendlyName = newName;
await unitOfWork.CommitAsync(ct);
logger.LogInformation("User {UserId} renamed device {DeviceId} to '{Name}'",
userId, deviceId, newName);
return true;
}
public async Task<bool> DeleteDeviceAsync(int userId, int deviceId, CancellationToken ct = default)
{
var device = await unitOfWork.ClientDeviceRepository.GetClientDeviceById(deviceId, userId, ct);
if (device == null)
{
throw new KavitaException("client-device-doesnt-exist");
}
device.IsActive = false;
await unitOfWork.CommitAsync(ct);
logger.LogInformation("User {UserId} removed device {DeviceId}", userId, deviceId);
return true;
}
public async Task UpdateFriendlyNameAsync(int userId, UpdateClientDeviceNameDto dto, CancellationToken ct = default)
{
var device = await unitOfWork.ClientDeviceRepository.GetClientDeviceById(dto.DeviceId, userId, ct)
?? throw new KavitaException("client-device-doesnt-exist");
if (!string.IsNullOrWhiteSpace(dto.Name))
{View on GitHub (pinned to 9c3e540000)
Solutions
- Refresh the device list in the UI before retrying the delete
- Verify the device ID in the request matches an active device returned by the list-devices endpoint
- Handle the KavitaException in the controller and return a 404 or user-friendly 'device not found' message
Example fix
// Controller-level guard before calling the service:
// var exists = await unitOfWork.ClientDeviceRepository.GetClientDeviceById(deviceId, userId);
// if (exists == null) return NotFound("Device not found"); Defensive patterns
Strategy: try-catch
Validate before calling
// Verify device exists before deletion:
// var device = await unitOfWork.ClientDeviceRepository.GetClientDeviceById(deviceId, userId, ct);
// if (device == null) return NotFound("Device not found or already removed"); Try / catch
// try {
// await clientDeviceService.DeleteDeviceAsync(userId, deviceId, ct);
// return Ok();
// } catch (KavitaException ex) when (ex.Message == "client-device-doesnt-exist") {
// return NotFound(new { error = "This device has already been removed." });
// } Prevention
- Refresh the device list in the UI before performing delete operations
- Handle stale device IDs gracefully with a user-friendly message
- Use optimistic concurrency checks if concurrent device management is expected
When it happens
Trigger: User attempts to delete a client device whose ID was already removed; user sends a delete request with a stale device ID from a cached UI; the device ID was tampered with in the request.
Common situations: The UI's device list is stale after another session deleted a device; race condition where two tabs attempt to delete the same device; client-side caching of device IDs across sessions.
Related errors
- library-doesnt-exist
- collection-doesnt-exist
- device-not-created
- device-doesnt-exist
- Source directory does not exist or could not be found:
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/9f38b51f251c28c8.
Report an issue: GitHub.