Steps to reproduce
Describe the bug
When downloading a chapter from a source protected by Cloudflare (in my case, HentaiHand) via FlareSolverr, the enqueueChapterDownload / startDownloader GraphQL mutations intermittently fail with:
kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 30000 ms
at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:281)
at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:243)
This appears to be a fixed 30-second execution timeout on the GraphQL server side. However, server.flareSolverrTimeout is documented and configurable, defaulting to 60 seconds — the time FlareSolverr is allowed to spend solving a Cloudflare challenge.
Since the GraphQL timeout (30s, apparently not configurable) is shorter than the FlareSolverr timeout it can end up waiting on (up to 60s by default), any challenge that takes longer than 30 seconds to solve causes the mutation to fail — even though FlareSolverr would have succeeded shortly after. This produces intermittent failures: the same source/chapter sometimes downloads fine (when the Cloudflare session is already warm, or the challenge resolves quickly) and sometimes fails outright with the timeout above, with no retry benefit unless enough time is manually left between attempts for the FlareSolverr session to become cached.
Steps to reproduce
Configure a source that is behind Cloudflare and requires a fresh challenge solve (no cached FlareSolverr session yet).
Enable FlareSolverr in Settings → Cloudflare bypass, with default/typical settings (flareSolverrTimeout = 60).
Trigger a chapter download (via WebUI or the GraphQL API directly, e.g. enqueueChapterDownload + startDownloader) for a chapter on that source when no FlareSolverr session is cached yet.
If the Cloudflare challenge takes longer than ~30 seconds to solve, the mutation fails with the timeout above, even though FlareSolverr may still be in the process of resolving it.
Expected behavior
Either:
The GraphQL execution timeout for download-related mutations should be configurable, and/or
It should be set to a value at least equal to (ideally somewhat greater than) server.flareSolverrTimeout, so that a Cloudflare-protected source isn't penalized by a client-facing timeout shorter than the tool meant to bypass its protection.
Actual behavior
Downloads intermittently fail with a 30-second GraphQL execution timeout that is independent of, and shorter than, the configured FlareSolverr timeout — producing confusing, hard-to-diagnose intermittent failures that look site-specific but are actually a timeout mismatch.
Environment
Suwayomi-Server version: v2.3.2243 (stable, official Docker image ghcr.io/suwayomi/tachidesk:stable)
Deployment: Docker (Docker Desktop on Windows, WSL2 backend)
FlareSolverr: running as a companion container (ghcr.io/flaresolverr/flaresolverr:latest), reachable and functional (manually verified via /v1 endpoint, resolves in a few seconds when no active challenge)
Source/extension affected: tachiyomi-all.hentaihand-v1.4.10.jar
Additional context
I confirmed this is not a network, DNS, permissions, or database issue on my end:
The Suwayomi container has working outbound connectivity (tested with curl to multiple hosts, 200/301 responses).
FlareSolverr is reachable from the Suwayomi container (200 on /) and resolves the target site successfully when queried directly.
Extensions and downloads directories have correct ownership/permissions inside the container.
The database (H2) is intact and correctly migrated.
The failure is reproducible identically whether triggered from the WebUI "Download" button or by calling the GraphQL mutations directly via a raw HTTP request — ruling out any client-side (frontend) cause.
I'd be happy to provide further logs or test a patch if one is proposed.
Expected behavior
Downloads intermittently fail with a 30-second GraphQL execution timeout that is independent of, and shorter than, the configured FlareSolverr timeout — producing confusing, hard-to-diagnose intermittent failures that look site-specific but are actually a timeout mismatch.
Actual behavior
The GraphQL execution timeout for download-related mutations should be configurable, and/or
It should be set to a value at least equal to (ideally somewhat greater than) server.flareSolverrTimeout, so that a Cloudflare-protected source isn't penalized by a client-facing timeout shorter than the tool meant to bypass its protection.
Suwayomi-Server version
v2.3.2243 (stable, docker)
Used database
H2
Server operating system
Docker (Windows host, WSL2 backend)
Server Desktop Environment
No response
Server JVM version
java -version
Used client name
Suwayomi-WebUI
Client version
r3379
Used web browser
Samsung Browser and Opera
Client operating system
Windows 11
Other details
No response
Acknowledgements
Steps to reproduce
Describe the bug
When downloading a chapter from a source protected by Cloudflare (in my case, HentaiHand) via FlareSolverr, the enqueueChapterDownload / startDownloader GraphQL mutations intermittently fail with:
kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 30000 ms
at kotlinx.coroutines.TimeoutKt.TimeoutCancellationException(Timeout.kt:281)
at kotlinx.coroutines.TimeoutCoroutine.run(Timeout.kt:243)
This appears to be a fixed 30-second execution timeout on the GraphQL server side. However, server.flareSolverrTimeout is documented and configurable, defaulting to 60 seconds — the time FlareSolverr is allowed to spend solving a Cloudflare challenge.
Since the GraphQL timeout (30s, apparently not configurable) is shorter than the FlareSolverr timeout it can end up waiting on (up to 60s by default), any challenge that takes longer than 30 seconds to solve causes the mutation to fail — even though FlareSolverr would have succeeded shortly after. This produces intermittent failures: the same source/chapter sometimes downloads fine (when the Cloudflare session is already warm, or the challenge resolves quickly) and sometimes fails outright with the timeout above, with no retry benefit unless enough time is manually left between attempts for the FlareSolverr session to become cached.
Steps to reproduce
Configure a source that is behind Cloudflare and requires a fresh challenge solve (no cached FlareSolverr session yet).
Enable FlareSolverr in Settings → Cloudflare bypass, with default/typical settings (flareSolverrTimeout = 60).
Trigger a chapter download (via WebUI or the GraphQL API directly, e.g. enqueueChapterDownload + startDownloader) for a chapter on that source when no FlareSolverr session is cached yet.
If the Cloudflare challenge takes longer than ~30 seconds to solve, the mutation fails with the timeout above, even though FlareSolverr may still be in the process of resolving it.
Expected behavior
Either:
The GraphQL execution timeout for download-related mutations should be configurable, and/or
It should be set to a value at least equal to (ideally somewhat greater than) server.flareSolverrTimeout, so that a Cloudflare-protected source isn't penalized by a client-facing timeout shorter than the tool meant to bypass its protection.
Actual behavior
Downloads intermittently fail with a 30-second GraphQL execution timeout that is independent of, and shorter than, the configured FlareSolverr timeout — producing confusing, hard-to-diagnose intermittent failures that look site-specific but are actually a timeout mismatch.
Environment
Suwayomi-Server version: v2.3.2243 (stable, official Docker image ghcr.io/suwayomi/tachidesk:stable)
Deployment: Docker (Docker Desktop on Windows, WSL2 backend)
FlareSolverr: running as a companion container (ghcr.io/flaresolverr/flaresolverr:latest), reachable and functional (manually verified via /v1 endpoint, resolves in a few seconds when no active challenge)
Source/extension affected: tachiyomi-all.hentaihand-v1.4.10.jar
Additional context
I confirmed this is not a network, DNS, permissions, or database issue on my end:
The Suwayomi container has working outbound connectivity (tested with curl to multiple hosts, 200/301 responses).
FlareSolverr is reachable from the Suwayomi container (200 on /) and resolves the target site successfully when queried directly.
Extensions and downloads directories have correct ownership/permissions inside the container.
The database (H2) is intact and correctly migrated.
The failure is reproducible identically whether triggered from the WebUI "Download" button or by calling the GraphQL mutations directly via a raw HTTP request — ruling out any client-side (frontend) cause.
I'd be happy to provide further logs or test a patch if one is proposed.
Expected behavior
Downloads intermittently fail with a 30-second GraphQL execution timeout that is independent of, and shorter than, the configured FlareSolverr timeout — producing confusing, hard-to-diagnose intermittent failures that look site-specific but are actually a timeout mismatch.
Actual behavior
The GraphQL execution timeout for download-related mutations should be configurable, and/or
It should be set to a value at least equal to (ideally somewhat greater than) server.flareSolverrTimeout, so that a Cloudflare-protected source isn't penalized by a client-facing timeout shorter than the tool meant to bypass its protection.
Suwayomi-Server version
v2.3.2243 (stable, docker)
Used database
H2
Server operating system
Server Desktop Environment
No response
Server JVM version
java -version
Used client name
Suwayomi-WebUI
Client version
r3379
Used web browser
Samsung Browser and Opera
Client operating system
Windows 11
Other details
No response
Acknowledgements