Skip to content

MangaUpdates 400 error on empty localized name kills entire provider chain #313

@xxxarmitagexxx

Description

@xxxarmitagexxx

Summary

When a series in Kavita has no localized name set, as is the default behavior for most Mangas source, Kavita returns an empty string "" for that field. Komf picks it up as an alternative title and includes it in the search title list. When MangaUpdates receives a search request with an empty search field, it returns a 400 Bad Request. Komf treats this as a fatal provider error and aborts the entire matching attempt — no other configured providers (AniList, MangaBaka, etc.) are tried for that series.


Steps to reproduce

  1. Have a series in Kavita with no localized name set (this is the default state for any series that hasn't had one manually entered).
  2. Configure Komf with MangaUpdates enabled at a higher priority than other providers.
  3. Trigger a library scan or metadata refresh for that series.
  4. Observe: MangaUpdates is called twice — once with the actual series title, once with "". The second call returns 400. No other provider runs.

Tested with "Frieren - Beyond Journey's End" and "Witch Hat Atelier" in Kavita, which are both referenced in MangaUpdate as their Japanese romanized title.


Root cause

Two separate issues combine to produce this:

Issue 1 — Missing blank check in KavitaMediaServerClientAdapter

KavitaMediaServerClientAdapter.kt maps Kavita's localizedName field to alternativeTitles:

alternativeTitles = series.localizedName?.let { listOf(MediaServerAlternativeTitle("Localized", it)) }
    ?: emptyList()

The ?.let guards against null but not against "". Kavita returns "" when no localized name is set, so the guard passes and the empty string ends up in the list.

Issue 2 — ProviderException escapes firstNotNullOfOrNull in MetadataService

matchSeries() wraps every provider exception into a ProviderException and re-throws it:

val result = try {
    provider.matchSeriesMetadata(...)
} catch (e: Exception) {
    throw ProviderException(provider.providerName(), e)
}

The caller uses firstNotNullOfOrNull to iterate providers in priority order:

metadataProviders.providers(...).firstNotNullOfOrNull { provider ->
    matchSeries(series, books, searchTitles, provider, null, eventFlow)
        ?.let { provider to it }
}

firstNotNullOfOrNull only handles null — it doesn't catch exceptions. So when MangaUpdates throws on the empty string, the exception escapes the loop and the remaining providers are never reached. This means a single provider failure on one search title can silently block all fallback providers for the entire series.


Expected behaviour

  • KavitaMediaServerClientAdapter should skip blank localized names rather than include them as alternative titles.
  • matchSeries / firstNotNullOfOrNull should treat a provider error as a non-fatal per-provider failure, log it, and continue to the next provider in the chain.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions