Kareadita/Kavita · error · KavitaException

Path not found in CBL repository: {path}

Error message

Path not found in CBL repository: {path}

What it means

Thrown in CblGithubService's 404 handler after FetchDirectoryFromGithub gets a FlurlHttpException with StatusCode 404. It means the GitHub contents API could not find the requested path in the DieselTech/CBL-ReadingLists repository - either the path never existed, was renamed/moved, or the leading-slash normalization produced a wrong key.

Source

Thrown at Kavita.Services/ReadingLists/CblGithubService.cs:225

            if (rateLimit.IsExhausted)
            {
                var resetsIn = rateLimit.ResetsAtUtc.HasValue
                    ? $" Resets at {rateLimit.ResetsAtUtc.Value:HH:mm} UTC."
                    : string.Empty;

                _logger.LogWarning("GitHub API rate limit exhausted.{ResetsIn}", resetsIn);
                throw new KavitaException(
                    $"GitHub API rate limit exhausted.{resetsIn} Cached data may still be available.");
            }

            _logger.LogWarning(ex, "GitHub API returned 403 for CBL repo");
            throw new KavitaException("GitHub API access denied. Please try again later.");
        }
        catch (FlurlHttpException ex) when (ex.StatusCode == 404)
        {
            _logger.LogWarning("CBL repo path not found: {Path}", path.Sanitize());
            throw new KavitaException($"Path not found in CBL repository: {path}");
        }
    }

    private CblRepoCache LoadCache()
    {
        var cachePath = GetCacheFilePath();
        if (!File.Exists(cachePath)) return new CblRepoCache();

        try
        {
            var json = File.ReadAllText(cachePath);
            return JsonSerializer.Deserialize<CblRepoCache>(json) ?? new CblRepoCache();
        }
        catch (Exception ex)
        {
            _logger.LogWarning(ex, "Failed to read CBL repo cache, starting fresh");
            return new CblRepoCache();
        }

View on GitHub (pinned to 9c3e540000)

Solutions

  1. Browse from the repo root and navigate to the correct path rather than deep-linking.
  2. Invalidate the local cache (InvalidateCache) so stale directory keys are dropped, then re-browse.
  3. Verify the exact path against the GitHub web UI for the DieselTech/CBL-ReadingLists repo.
  4. Re-check NormalizePath output for the input to ensure no segments are lost.

Example fix

// before
var content = await cblGithubService.GetFileContent("lists/old-name.cbl");

// after
cblGithubService.InvalidateCache();
var browse = await cblGithubService.BrowseRepo("lists");
var real = browse.Items.FirstOrDefault(i => i.Name.EndsWith(".cbl"))?.Path;
var content = real is null ? null : await cblGithubService.GetFileContent(real);
Defensive patterns

Strategy: validation

Validate before calling

var browse = await cblGithubService.BrowseRepo(parentDir);
if (!browse.Items.Any(i => i.Path == filePath))
    return NotFound($"Path {filePath} not found in CBL repo");
var content = await cblGithubService.GetFileContent(filePath);

Type guard

static bool PathExistsInRepo(string path, IEnumerable<CblRepoItemDto> items) => items.Any(i => i.Path == path);

Try / catch

try { return await cblGithubService.GetFileContent(filePath); }
catch (KavitaException ex) when (ex.Message.Contains("Path not found"))
{ cblGithubService.InvalidateCache(); return NotFound(ex.Message); }

Prevention

When it happens

Trigger: Browsing or fetching a file/dir path that does not exist in the CBL repo: a stale cached path after the repo was restructured, a user-typed path with a typo, or NormalizePath stripping a needed segment.

Common situations: The upstream CBL repo renamed/moved directories; a user copy-pasted an old link; NormalizePath collapsed './' or trailing slash in a way that mismatches the API; or forceRefresh bypassed a still-valid cache entry pointing at a deleted folder.

Related errors


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