Kareadita/Kavita · error · KavitaException
errors.theme-manual-upload
errors.theme-manual-upload
Error message
errors.theme-manual-upload
What it means
Thrown by SiteThemeService.CreateThemeFromFile when the uploaded theme's temp file does not exist on disk when processing starts (directoryService.FileSystem.File.Exists(tempFile) is false). The upload pipeline writes the form file to temp, then hands the path to CreateThemeFromFile; if that file is gone or never written, the upload cannot proceed. KavitaException('errors.theme-manual-upload') is thrown. ThemeController's upload-theme endpoint does not catch it, so it surfaces as HTTP 500 with the raw key 'errors.theme-manual-upload'.
Source
Thrown at Kavita.Services/SiteThemeService.cs:417
var siteTheme = await unitOfWork.SiteThemeRepository.GetTheme(siteThemeId);
if (siteTheme == null) return;
await RemoveTheme(siteTheme);
}
/// <summary>
/// This assumes a file is already in temp directory and will be used for
/// </summary>
/// <param name="tempFile"></param>
/// <param name="username"></param>
/// <param name="ct"></param>
/// <returns></returns>
public async Task<SiteTheme> CreateThemeFromFile(string tempFile, string username, CancellationToken ct = default)
{
if (!directoryService.FileSystem.File.Exists(tempFile))
{
logger.LogInformation("Unable to create theme from manual upload as file not in temp");
throw new KavitaException("errors.theme-manual-upload");
}
var filename = directoryService.FileSystem.FileInfo.New(tempFile).Name;
var themeName = Path.GetFileNameWithoutExtension(filename);
if (await unitOfWork.SiteThemeRepository.GetThemeDtoByName(themeName) != null)
{
throw new KavitaException("errors.theme-already-in-use");
}
directoryService.CopyFileToDirectory(tempFile, directoryService.SiteThemeDirectory);
var finalLocation = directoryService.FileSystem.Path.Join(directoryService.SiteThemeDirectory, filename);
// Create a new entry and note that this is downloaded
var theme = new SiteTheme()
{View on GitHub (pinned to 9c3e540000)
Solutions
- Verify the TempDirectory exists and the Kavita process has write permission and free space.
- Retry the upload; transient cleanup/contention races usually clear.
- Ensure TempDirectory is on persistent, writable storage and not cleared by an external job mid-upload.
Defensive patterns
Strategy: try-catch
Try / catch
try {
await api.uploadTheme(file);
} catch (e) {
// HTTP 500 raw key 'errors.theme-manual-upload': temp file missing/unwritable.
notify('Upload failed (temp directory not writable or full). Free space and retry.');
} Prevention
- Ensure the TempDirectory is writable with adequate free space.
- Keep TempDirectory persistent and not cleared by external jobs during uploads.
- Retry the upload once; transient temp races usually clear.
When it happens
Trigger: POST /api/theme/upload-theme where the temp file write failed, the file was removed by a concurrent temp cleanup before processing, the TempDirectory is not writable, or the disk is full.
Common situations: TempDirectory on a read-only/unmounted volume; disk full; aggressive nightly/temp cleanup racing with a slow upload; container with an ephemeral or permission-restricted temp dir.
Related errors
- errors.theme-already-in-use
- errors.font-manual-upload
- theme-doesnt-exist
- errors.delete-theme-in-use
- invalid-filename
AI-assisted analysis of Kareadita/Kavita@9c3e540000 (2026-08-13).
Data as JSON: /api/errors/e90f4b98bde93e7a.
Report an issue: GitHub.