{"record":{"id":"3beab89f6d6948a4","repo":"denoland/deno","slug":"restore-test-permissions-token-does-not-match-the-3beab8","errorCode":null,"errorMessage":"restore test permissions token does not match the stored token","messagePattern":"restore test permissions token does not match the stored token","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/ops/testing.rs","lineNumber":112,"sourceCode":"    panic!(\"pledge test permissions called before restoring previous pledge\");\n  }\n  state.put::<PermissionsHolder>(PermissionsHolder(token, parent_permissions));\n\n  // NOTE: This call overrides current permission set for the worker\n  state.put::<PermissionsContainer>(worker_permissions);\n\n  Ok(token)\n}\n\n#[op2]\npub fn op_restore_test_permissions(\n  state: &mut OpState,\n  #[serde] token: Uuid,\n) -> Result<(), JsErrorBox> {\n  match state.try_take::<PermissionsHolder>() {\n    Some(permissions_holder) => {\n      if token != permissions_holder.0 {\n        panic!(\n          \"restore test permissions token does not match the stored token\"\n        );\n      }\n\n      let permissions = permissions_holder.1;\n      state.put::<PermissionsContainer>(permissions);\n      Ok(())\n    }\n    _ => Err(JsErrorBox::generic(\"no permissions to restore\")),\n  }\n}\n\nstatic NEXT_ID: AtomicUsize = AtomicUsize::new(0);\n\n#[allow(clippy::too_many_arguments, reason = \"op\")]\n#[op2]\nfn op_register_test(\n  state: &mut OpState,","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/cli/ops/testing.rs#L94-L130","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass the exact token from the corresponding pledge call, kept in a single local variable","Ensure restores are 1:1 with pledges and never reordered or duplicated","File a Deno bug if stock `deno test` reproduces it"],"exampleFix":"// before\nconst t = pledge(args);\nrestore(oldToken);              // stale token -> panic\n// after\nconst t = pledge(args);\ntry { runTests(); } finally { restore(t); }","handlingStrategy":"validation","validationCode":"let current = null;\nfunction pledge(args) { current = pledgeOp(args); return current; }\nfunction restore(token) {\n  if (token === null || token !== current) throw new Error('token mismatch; aborting restore');\n  restoreOp(current); current = null;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass the token straight from pledge's return value into restore","Add a harness invariant test: every pledge is followed by exactly one matching restore"],"tags":["permissions","testing","token","internal-ops","panic"],"backgroundTag":"token-mismatch","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}