{"record":{"id":"e90f4b98bde93e7a","repo":"Kareadita/Kavita","slug":"errors-theme-manual-upload","errorCode":"errors.theme-manual-upload","errorMessage":"errors.theme-manual-upload","messagePattern":"errors\\.theme-manual-upload","errorType":"exception","errorClass":"KavitaException","httpStatus":400,"severity":"error","filePath":"Kavita.Services/SiteThemeService.cs","lineNumber":417,"sourceCode":"        var siteTheme = await unitOfWork.SiteThemeRepository.GetTheme(siteThemeId);\n        if (siteTheme == null) return;\n\n        await RemoveTheme(siteTheme);\n    }\n\n    /// <summary>\n    /// This assumes a file is already in temp directory and will be used for\n    /// </summary>\n    /// <param name=\"tempFile\"></param>\n    /// <param name=\"username\"></param>\n    /// <param name=\"ct\"></param>\n    /// <returns></returns>\n    public async Task<SiteTheme> CreateThemeFromFile(string tempFile, string username, CancellationToken ct = default)\n    {\n        if (!directoryService.FileSystem.File.Exists(tempFile))\n        {\n            logger.LogInformation(\"Unable to create theme from manual upload as file not in temp\");\n            throw new KavitaException(\"errors.theme-manual-upload\");\n        }\n\n\n        var filename = directoryService.FileSystem.FileInfo.New(tempFile).Name;\n        var themeName = Path.GetFileNameWithoutExtension(filename);\n\n        if (await unitOfWork.SiteThemeRepository.GetThemeDtoByName(themeName) != null)\n        {\n            throw new KavitaException(\"errors.theme-already-in-use\");\n        }\n\n        directoryService.CopyFileToDirectory(tempFile, directoryService.SiteThemeDirectory);\n        var finalLocation = directoryService.FileSystem.Path.Join(directoryService.SiteThemeDirectory, filename);\n\n\n        // Create a new entry and note that this is downloaded\n        var theme = new SiteTheme()\n        {","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/Kareadita/Kavita/blob/9c3e5400007f8a0282f7d883f2ad5e71716e514d/Kavita.Services/SiteThemeService.cs#L399-L435","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await api.uploadTheme(file);\n} catch (e) {\n  // HTTP 500 raw key 'errors.theme-manual-upload': temp file missing/unwritable.\n  notify('Upload failed (temp directory not writable or full). Free space and retry.');\n}","preventionTips":["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."],"tags":["theme","filesystem","upload","temp","admin"],"backgroundTag":null,"analyzedSha":"9c3e5400007f8a0282f7d883f2ad5e71716e514d","analyzedAt":"2026-08-13T19:06:05.897Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}