Zemer Cipher defines four exception types. Most public API methods returnDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ZemerTeam/zemer-cipher/llms.txt
Use this file to discover all available pages before exploring further.
null rather than throwing on recoverable failures — exceptions are reserved for conditions where the caller must explicitly handle or propagate the error.
CancellationException (from Kotlin coroutines) is always rethrown unconditionally. None of the exception handlers in this library swallow cancellation, so cooperative cancellation of coroutines works correctly throughout.CipherException
com.zemer.cipher
Thrown when the cipher WebView itself fails — for example:
- The player JS file failed to load from the local file cache.
- The signature or n-transform JavaScript call returned
nullorundefined. - The JS bridge reported an error from inside the player JS evaluation.
CipherDeobfuscator catches CipherException internally and returns null after a single retry attempt, so callers rarely see this exception directly. If it surfaces to a caller, it means both the initial attempt and the retry failed at the WebView JS level.
CipherRendererGoneException
com.zemer.cipher
Thrown when the WebView renderer process has died (OOM kill or crash) or when a JS evaluation timed out (which is treated as an equivalent renderer death since a responsive renderer answers in milliseconds). The CipherWebView instance is permanently unusable after this exception and must be discarded — per Android documentation a WebView whose renderer process is gone cannot be reused.
CipherDeobfuscator catches this internally, calls RendererRecoveryPolicy.onFailure(), and returns null without a retry. A retry with a fresh CipherWebView is attempted on the next request if RendererRecoveryPolicy.shouldAttempt() permits it.
PoTokenException
com.zemer.cipher.potoken
Thrown by PoTokenGenerator.getWebClientPoToken() when a JavaScript-level error occurs during BotGuard token generation and the automatic retry with a fresh WebView also fails. This indicates that the BotGuard JS itself returned an error rather than the WebView being broken.
Callers that receive PoTokenException should fall through to non-web YouTube clients, which do not require a PoToken.
BadWebViewException
com.zemer.cipher.potoken
Thrown when the system WebView is fundamentally broken — most commonly an old Chromium version that throws a SyntaxError when parsing the BotGuard JavaScript.
PoTokenGenerator catches this internally, sets an internal webViewBadImpl = true flag, and returns null for all subsequent calls on the same instance. The condition is treated as permanent for that PoTokenGenerator instance: no further BotGuard attempts are made, avoiding repeated expensive WebView loads on a device where they can never succeed.
buildExceptionForJsError
com.zemer.cipher.potoken
Helper function used internally by PoTokenGenerator to map a raw JS error string to the correct exception type. Returns BadWebViewException if error contains the substring "SyntaxError", or PoTokenException for all other error strings.
The raw error string received from the JavaScript bridge (typically from a caught JS exception or an error callback).
BadWebViewException if the error indicates a SyntaxError (broken WebView); PoTokenException otherwise.
Exception Hierarchy Summary
| Exception | Package | Thrown by | Caught internally? |
|---|---|---|---|
CipherException | com.zemer.cipher | CipherWebView sig/n evaluation errors | Yes — CipherDeobfuscator retries once, then returns null |
CipherRendererGoneException | com.zemer.cipher | CipherWebView renderer death or timeout | Yes — CipherDeobfuscator calls onFailure(), returns null |
PoTokenException | com.zemer.cipher.potoken | PoTokenGenerator JS errors after retry | No — propagated to caller |
BadWebViewException | com.zemer.cipher.potoken | PoTokenGenerator on SyntaxError | Yes — sets webViewBadImpl, returns null permanently |