Kareadita/Kavita · error · KavitaException

device-not-created

Error message

device-not-created

What it means

Thrown by DeviceService.Update when the device with dto.Id is not found in the user's Devices collection. Despite the message 'device-not-created', this is actually a 'not found' error during an update operation — the name is misleading. The lookup uses SingleOrDefault(d => d.Id == dto.Id) on the in-memory collection.

Source

Thrown at Kavita.Services/DeviceService.cs:62

            if (!unitOfWork.HasChanges()) return existingDevice;
            if (await unitOfWork.CommitAsync(ct)) return existingDevice;
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "There was an error when creating your device");
            await unitOfWork.RollbackAsync(ct);
        }

        return null;
    }

    public async Task<Device?> Update(UpdateEmailDeviceDto dto, AppUser userWithDevices, CancellationToken ct = default)
    {
        try
        {
            var existingDevice = userWithDevices.Devices.SingleOrDefault(d => d.Id == dto.Id);
            if (existingDevice == null) throw new KavitaException("device-not-created");

            existingDevice.Name = dto.Name;
            existingDevice.Platform = dto.Platform;
            existingDevice.EmailAddress = dto.EmailAddress;

            if (!unitOfWork.HasChanges()) return existingDevice;
            if (await unitOfWork.CommitAsync(ct)) return existingDevice;
        }
        catch (Exception ex)
        {
            logger.LogError(ex, "There was an error when updating your device");
            await unitOfWork.RollbackAsync(ct);
        }

        return null;
    }

    public async Task<bool> Delete(AppUser userWithDevices, int deviceId, CancellationToken ct = default)

View on GitHub (pinned to 9c3e540000)

Solutions

  1. Refresh the device list before editing to get current device IDs
  2. Ensure the calling controller loads the user with Devices included before calling Update
  3. Handle the KavitaException and return a clear 'device not found' error to the client

Example fix

// Ensure devices are eagerly loaded:
// var user = await unitOfWork.UserRepository.GetUserByIdAsync(userId)
//     ?? throw new KavitaException("user-not-found");
// // Confirm user.Devices is populated via Include in the repository query
// await deviceService.Update(dto, user, ct);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the device exists before updating:
// var existing = userWithDevices.Devices?.SingleOrDefault(d => d.Id == dto.Id);
// if (existing == null) return NotFound("Device not found");

Type guard

// Confirm user has Devices loaded before calling Update:
// static bool IsDeviceInCollection(AppUser user, int deviceId) =>
//     user.Devices?.Any(d => d.Id == deviceId) ?? false;

Try / catch

// try {
//     var device = await deviceService.Update(dto, userWithDevices, ct);
//     return Ok(device);
// } catch (KavitaException ex) when (ex.Message == "device-not-created") {
//     return NotFound(new { error = "Device not found. It may have been removed." });
// }

Prevention

When it happens

Trigger: User edits a device that was already deleted; the device ID in the update DTO does not match any device the user owns; userWithDevices.Devices was not eagerly loaded (would make SingleOrDefault always return null).

Common situations: Stale device list in the UI after a device was removed; the user's Devices navigation collection wasn't loaded by the calling code; concurrent sessions where one deletes a device while another tries to update it.

Related errors


AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13). Data as JSON: /api/errors/3ec6dee1e245abe7. Report an issue: GitHub.