garrytan/gstack · error · Error
DENIED: ${qualified} is not on the CDP allowlist. Cause: den
Error message
DENIED: ${qualified} is not on the CDP allowlist.
Cause: deny-default posture; method has not been audited and added to cdp-allowlist.ts.
Action: if this method is genuinely needed, open a PR adding it to CDP_ALLOWLIST with a one-line justification + scope (tab|browser) + output (trusted|untrusted). What it means
Error "DENIED: ${qualified} is not on the CDP allowlist. Cause: deny-default posture; method has not been audited and added to cdp-allowlist.ts. Action: if this method is genuinely needed, open a PR adding it to CDP_ALLOWLIST with a one-line justification + scope (tab|browser) + output (trusted|untrusted)." thrown in garrytan/gstack.
Source
Thrown at browse/src/cdp-bridge.ts:135
raw: unknown;
entry: CdpAllowEntry;
}
/**
* Look up + acquire mutex + send + release. Throws structured errors on:
* - DENIED (method not on allowlist)
* - CDPMutexAcquireTimeout (lock contention exceeded budget)
* - CDPBridgeTimeout (CDP method itself didn't return in budget)
* - CDPSessionInvalidated (Playwright recreated context, session stale)
*/
export async function dispatchCdpCall(input: CdpDispatchInput): Promise<CdpDispatchResult> {
const qualified = `${input.domain}.${input.method}`;
const entry = lookupCdpMethod(qualified);
if (!entry) {
// Surface the denial via telemetry — this is the data that drives the
// next allow-list expansion (DX D9: cdp_method_denied counter).
logTelemetry({ event: 'cdp_method_denied', domain: input.domain, method: input.method });
throw new Error(
`DENIED: ${qualified} is not on the CDP allowlist.\n` +
`Cause: deny-default posture; method has not been audited and added to cdp-allowlist.ts.\n` +
`Action: if this method is genuinely needed, open a PR adding it to CDP_ALLOWLIST with a one-line justification + scope (tab|browser) + output (trusted|untrusted).`
);
}
// Acquire the right tier of lock.
const acquireStart = Date.now();
const release =
entry.scope === 'browser'
? await input.bm.acquireGlobalCdpLock(CDP_ACQUIRE_TIMEOUT_MS)
: await input.bm.acquireTabLock(input.tabId, CDP_ACQUIRE_TIMEOUT_MS);
const acquireMs = Date.now() - acquireStart;
logTelemetry({ event: 'cdp_method_lock_acquire_ms', domain: input.domain, method: input.method, ms: acquireMs });
logTelemetry({ event: 'cdp_method_called', domain: input.domain, method: input.method, allowed: true, scope: entry.scope });
try {
const page = input.bm.getPageForTab(input.tabId);
if (!page) {View on GitHub (pinned to 94993f7401)
When it happens
Trigger: Thrown at browse/src/cdp-bridge.ts:135 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of garrytan/gstack@94993f7401 (2026-08-12).
Data as JSON: /api/errors/abb860e4a20c7328.
Report an issue: GitHub.