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/testing.rs) backing `deno test`. Restore compares the caller-supplied UUID against the token stored at pledge time; a mismatch means the caller is trying to restore a different (stale or foreign) pledge, which would install the wrong permissions, so the op panics instead.

Source

Thrown at cli/ops/testing.rs:112

    panic!("pledge test permissions called before restoring previous pledge");
  }
  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_test(
  state: &mut OpState,

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Pass the exact token from the corresponding pledge call, kept in a single local variable
  2. Ensure restores are 1:1 with pledges and never reordered or duplicated
  3. File a Deno bug if stock `deno test` reproduces it

Example fix

// before
const t = pledge(args);
restore(oldToken);              // stale token -> panic
// after
const t = pledge(args);
try { runTests(); } finally { restore(t); }
Defensive patterns

Strategy: validation

Validate before calling

let current = null;
function pledge(args) { current = pledgeOp(args); return current; }
function restore(token) {
  if (token === null || token !== current) throw new Error('token mismatch; aborting restore');
  restoreOp(current); current = null;
}

Prevention

When it happens

Trigger: Calling op_restore_test_permissions with any UUID other than the one returned by the most recent op_pledge_test_permissions in that worker — stale cached token, token from another worker, or a second pledge that replaced the stored holder.

Common situations: Custom test-harness forks caching the token across pledge cycles; parallel restore calls racing; snippets copied with old tokens. Not reachable through normal Deno.test() usage.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/3beab89f6d6948a4. Report an issue: GitHub.