Skip to main content

Troubleshooting

Common failure modes and how to diagnose them. If your symptom isn't here, check the structured logs (logging.json = true makes them greppable) and the admin metrics tab — most operational questions are answerable from one of those two surfaces.

Resolver​

Many releases land in the review queue​

Check the review queue cards themselves. Every card shows the cleaned search query the resolver used and the cleanup rules that fired. Common patterns:

  • Cleaner missed a keyword. Look at uploader-specific patterns (e.g. a new keyword like Remastered). Add to [ingestion.cleanup.extra_format_keywords] and use the Retry button on the queue card.
  • Dice score just under threshold. The candidate is right but noisy title text drags the score. If this happens systematically for a known-good release shape, lower resolution_threshold (e.g. from 0.85 to 0.80). Don't drop it below 0.70 — false-positive risk rises sharply.
  • No candidates at all. The cleaned query produced no FTS hits. Try the Search provider modal manually — if the series is in MangaBaka, the cleaner is being too aggressive; flag it as a bug. If MangaBaka doesn't have it, Reject the release.

A release auto-resolved to the wrong series​

Use the Search provider modal to find the correct series, then click "Link" on the right hit. The release transitions to resolved with resolution_path = "manual". The wrong link is overwritten.

If a pattern of wrong matches surfaces (same uploader, same shape), file an issue with the cleaned query + the candidate's Dice score — the cleaner rule order may need a tweak.

Provider returned 503 Misconfigured​

The auth.admin_token config value is unset. Set it and restart. The 503 is intentional — distinct from 401 Unauthorized so a fresh deploy doesn't look like a credentialing bug.

Sources​

Nyaa source returns zero releases​

Check the admin Sources card:

  • last_error — if populated, the feed URL is wrong or Nyaa is unreachable. Verify with curl <feed_url> from the host.
  • fetched_count = 0 but no error — the feed is responding but empty for the configured filters. Try a less restrictive feed URL in a browser.
  • Stale last_polled_at — the scheduler isn't running the source. Verify cron is set and the source is enabled = true. The tsundoku poll --source <name> one-shot also works for diagnosis.

MangaUpdates legacy ID resolution looks stuck​

The mangaupdates_id_map table caches per-legacy-ID translations, including tombstones for dead IDs. To inspect:

sqlite3 ${data_dir}/db/tsundoku.db \
'SELECT legacy_id, modern_id, resolved_at FROM mangaupdates_id_map ORDER BY resolved_at DESC LIMIT 20'

Rate-limit recovery: the resolver throttles at 1 req/sec per host with exponential backoff on 429. A long outage tightens the next- allowed timestamp; failed lookups don't cache, so the next poll retries naturally.

Providers​

Refresh cache button takes a long time​

The MangaBaka dump is ~476 MB compressed. First-time refresh fetches, verifies SHA-1, extracts, and adds 8 indexes + an FTS5 mirror. On a modest machine this can take 3–5 minutes. Subsequent refreshes are faster because rotation reuses the extraction path.

If refresh-provider-cache hangs longer than that, kill it and check the host's network. The download supports resume via HTTP Range; rerun the refresh and it picks up where it left off.

Cache misses despite a recent refresh​

Two scenarios:

  • The series is genuinely missing from MangaBaka's dump. Enable api_fallback = true + api_key = "..." to fall back to the live API for cache misses.
  • The series exists but under a different foreign ID. Use the Search provider modal to find it manually.

A negative-cache tombstone may also be holding back retries. The TTL is negative_cache_ttl_days (default 7).

Database​

"database is locked" errors​

The connection pool is pinned to one writer, so this should be rare. If you see it: another process is holding a write lock. Verify only one tsundoku instance is running against the data dir.

The busy_timeout is 5000 ms — if the offending writer doesn't release within that window, you'll see the error.

Reset to a clean slate​

systemctl stop tsundoku
rm ${data_dir}/db/tsundoku.db
tsundoku migrate
# (optional) tsundoku refresh-provider-cache
systemctl start tsundoku

This drops every release, every series, every review-queue card. The MangaBaka offline cache survives — that's a separate file at ${data_dir}/cache/providers/mangabaka/series.sqlite. Delete it too if you want a full reset.

Logging​

tracing-subscriber honors RUST_LOG. Examples:

RUST_LOG=tsundoku=debug tsundoku serve
RUST_LOG=tsundoku=trace,sea_orm=warn tsundoku serve
RUST_LOG=tsundoku=debug,td_resolution=trace tsundoku serve

For JSON-structured logs (suitable for Loki / journald aggregators), set logging.json = true in config.

When to file an issue​

github.com/AshDevFr/tsundoku/issues.

Useful in the report:

  • tsundoku version (tsundoku --version or the GHCR tag).
  • The relevant config block (redact api_key and admin_token).
  • Logs at debug level around the failing operation.
  • For resolution bugs: the raw title from Nyaa, the cleaned query the card shows, and a screenshot of the review card if possible.