CloakHQ/CloakBrowser · warning
[cloakbrowser] CLOAKBROWSER_WIDEVINE_CDM is set but has no m
Error message
[cloakbrowser] CLOAKBROWSER_WIDEVINE_CDM is set but has no manifest.json; skipping Widevine hint seeding
What it means
The environment variable CLOAKBROWSER_WIDEVINE_CDM points to a directory that does not contain a manifest.json, so the library cannot identify a valid Widevine CDM and skips seeding the Widevine hint into the profile. This is a best-effort warning: the launch proceeds, but DRM-protected media (e.g. Netflix, Spotify web) will not use your custom CDM.
Source
Thrown at js/src/widevine.ts:100
* Write the Widevine CDM hint file into a persistent profile before launch.
* `binaryPath` is the resolved chrome executable; the CDM is looked for next to
* it. No-op on non-Linux, when disabled via CLOAKBROWSER_WIDEVINE, or when no
* sideloaded CDM is present. Never throws — a failure must not break launch.
*/
export function seedWidevineHint(userDataDir: string, binaryPath: string): void {
if (process.platform !== "linux") return;
if (seedingDisabled()) return;
// Empty userDataDir = Playwright's ephemeral profile (its own temp dir);
// a persistent hint can't be placed there, and "" would pollute the CWD.
if (!userDataDir) return;
// Everything below is best-effort and must never break the browser launch,
// so the whole body (resolution + write) is guarded.
try {
const cdmDir = resolveWidevineCdmDir(binaryPath);
if (cdmDir === null) {
if (process.env.CLOAKBROWSER_WIDEVINE_CDM !== undefined) {
console.warn(
"[cloakbrowser] CLOAKBROWSER_WIDEVINE_CDM is set but has no manifest.json; " +
"skipping Widevine hint seeding",
);
}
return;
}
const hintDir = path.join(userDataDir, "WidevineCdm");
fs.mkdirSync(hintDir, { recursive: true });
const hintFile = path.join(hintDir, HINT_FILENAME);
// cdmDir is already absolute/resolved.
const content = JSON.stringify({ Path: cdmDir });
try {
if (isFile(hintFile) && fs.readFileSync(hintFile, "utf-8") === content) {
return; // already seeded correctly
}
} catch {View on GitHub (pinned to d6bad5de26)
Solutions
- Verify the directory actually contains manifest.json alongside the CDM library: ls $CLOAKBROWSER_WIDEVINE_CDM.
- Point CLOAKBROWSER_WIDEVINE_CDM at the exact versioned CDM folder that contains manifest.json.
- Re-download/re-extract the Widevine CDM if the extraction was partial.
- If you don't need DRM, unset the variable to silence the warning.
Example fix
# before export CLOAKBROWSER_WIDEVINE_CDM=/opt/widevine # contains only libwidevinecdm.so # after export CLOAKBROWSER_WIDEVINE_CDM=/opt/widevine/4.10.2559.0 # contains manifest.json + libwidevinecdm.so
Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
import path from 'node:path';
const cdm = process.env.CLOAKBROWSER_WIDEVINE_CDM;
if (cdm && !fs.existsSync(path.join(cdm, 'manifest.json'))) {
throw new Error(`CLOAKBROWSER_WIDEVINE_CDM has no manifest.json: ${cdm}`);
} Type guard
const isCdmDirWithManifest = (dir: string): boolean => fs.existsSync(path.join(dir, 'manifest.json'));
Prevention
- Validate the CDM directory layout in deployment scripts (manifest.json + CDM shared library).
- Pin and re-extract the CDM atomically; don't hand-copy single files.
- Unset the variable if DRM is not needed.
When it happens
Trigger: Setting CLOAKBROWSER_WIDEVINE_CDM=/path/to/dir where the dir lacks manifest.json (only e.g. libwidevinecdm.so, or wrong path), then calling launchPersistentContext, which calls seedWidevineHint.
Common situations: Pointing at the wrong directory level (the folder above the versioned CDM folder), incomplete CDM extraction, or a path to a file rather than the CDM directory. Also happens when the built-in resolution found nothing and the env var was the user's attempted override.
Related errors
- GeoIP resolution failed: GeoIP database is unavailable
- Viewport size not available
- Invalid port: {s}
- StealthWorldUnavailableError
- CLOAKBROWSER_BINARY_PATH set to '{local_override}' but file
AI-assisted analysis of CloakHQ/CloakBrowser@d6bad5de26 (2026-08-28).
Data as JSON: /api/errors/905c2fa824ea941d.
Report an issue: GitHub.