denoland/deno · error
restore test permissions token does not match the stored tok
Error message
restore test permissions token does not match the stored token
What it means
Panic in the op_restore_test_permissions op (cli/ops/bench.rs) backing `deno bench`. Each pledge returns a random UUID token stored with the saved permissions; restore must present the matching token. If the caller passes a token different from the one currently stored (stale token from an earlier pledge, regenerated token, or cross-worker mix-up), the op panics rather than restoring the wrong permissions.
Source
Thrown at cli/ops/bench.rs:83
}
state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));
// NOTE: This call overrides current permission set for the worker
state.put::<PermissionsContainer>(worker_permissions);
Ok(token)
}
#[op2]
pub fn op_restore_test_permissions(
state: &mut OpState,
#[serde] token: Uuid,
) -> Result<(), JsErrorBox> {
match state.try_take::<PermissionsHolder>() {
Some(permissions_holder) => {
if token != permissions_holder.0 {
panic!(
"restore test permissions token does not match the stored token"
);
}
let permissions = permissions_holder.1;
state.put::<PermissionsContainer>(permissions);
Ok(())
}
_ => Err(JsErrorBox::generic("no permissions to restore")),
}
}
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
#[allow(clippy::too_many_arguments, reason = "op")]
#[op2]
fn op_register_bench(
state: &mut OpState,View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Propagate the exact token returned by the pledge call to the matching restore call (keep it in a local variable, single owner)
- Guarantee one restore per pledge, in a finally block, with no interleaving pledges
- If stock `deno bench` triggers this, file a Deno issue with the reproduction
Example fix
// before
const t = pledge(args);
restore('00000000-0000-0000-0000-000000000000'); // wrong token
// after
const t = pledge(args);
try { runBench(); } finally { restore(t); } Defensive patterns
Strategy: validation
Validate before calling
// keep exactly one live token and reuse it for the matching restore
let liveToken = null;
function pledge(args) { liveToken = pledgeOp(args); return liveToken; }
function restore(token) {
if (token !== liveToken) throw new Error('stale pledge token; refusing to call restore');
restoreOp(token); liveToken = null;
} Prevention
- Store the pledge token in a single local scope and pass it to exactly one restore
- Never cache tokens across pledge cycles or share them between workers
When it happens
Trigger: Calling op_restore_test_permissions with a UUID that is not the token returned by the most recent op_pledge_test_permissions call in the same worker — e.g. reusing a token after a second pledge replaced the stored holder.
Common situations: Custom bench-harness forks caching tokens across pledge cycles; concurrent paths in harness code both trying to restore; copy-paste of harness snippets with hardcoded/old tokens. Not reachable through normal Deno.bench() usage.
Related errors
- pledge test permissions called before restoring previous ple
- restore test permissions token does not match the stored tok
- pledge test permissions called before restoring previous ple
- BenchContext::end() has already been invoked
- invalid doc test hashbang: {} ({reason})
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/8935e272b40ab001.
Report an issue: GitHub.