{"record":{"id":"e7f88db6a3f94d4b","repo":"jax-ml/jax","slug":"attempting-to-deallocate-allocation-with-key-key","errorCode":null,"errorMessage":"Attempting to deallocate allocation with key `{key}` that is not a `Buffer`.","messagePattern":"Attempting to deallocate allocation with key `(.+?)` that is not a `Buffer`\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/pallas/mosaic/interpret/shared_memory.py","lineNumber":480,"sourceCode":"\n        if self.enable_logging and logging_info is not None:\n          self._log(\n              logging_info.format(\n                  f\"{key=}, {ref_count=}.\\nvalue_shape={value.shape},\"\n                  f\" logical_shape={buff.logical_shape},\"\n                  f\" content_shape={buff.shape}\",\n                  line_prefix=\"`allocate_buffer`\",\n              )\n          )\n\n  def deallocate_buffer(\n      self, key: MemKey, logging_info: interpret_utils.LoggingInfo | None = None\n  ):\n    \"\"\"Decreases the ref count for the buffer with `key` and deallocates the buffer if the ref count is zero.\"\"\"\n    with self.lock:\n      buff = self.mem[key]\n      if not isinstance(buff, Buffer):\n        raise ValueError(\n            f\"Attempting to deallocate allocation with key `{key}` that is not\"\n            \" a `Buffer`.\"\n        )\n\n      buff.decrease_ref_count()\n      if buff.has_zero_ref_count():\n        # TODO(paulbib): delete buffer from race detection state as well\n        self.mem.pop(key)\n        self.deallocated_bytes += buff.size\n        del buff\n\n        if self.enable_logging and logging_info is not None:\n          self._log(\n              logging_info.format(f\"{key=}.\", line_prefix=\"`deallocate_buffer`\")\n          )\n\n      should_collect = self.deallocated_bytes > 100_000_000\n      if should_collect:","sourceCodeStart":462,"sourceCodeEnd":498,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/pallas/mosaic/interpret/shared_memory.py#L462-L498","documentation":"The interpret-mode shared memory manager's deallocate_buffer looked up a memory key whose stored object is not a Buffer (e.g. a Semaphore). The ref-count-based deallocation path only applies to Buffers.","triggerScenarios":"Calling deallocate_buffer with a key that was registered for a semaphore or other non-Buffer allocation due to key collision between fixed-ID semaphores and buffer keys.","commonSituations":"Client-managed memory keys colliding with internal semaphore IDs; mixed allocation/deallocation bookkeeping bugs in custom interpret-mode tooling.","solutions":["Verify the key refers to an allocation created via allocate_buffer, not a semaphore","Avoid key collisions between fixed-ID semaphores and buffer keys","Audit custom alloc/dealloc call sites to keep keys symmetric"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def is_buffer_key(mgr, key):\n    with mgr.lock:\n        return isinstance(mgr.mem.get(key), Buffer)","tryCatchPattern":"try:\n    mgr.deallocate_buffer(key)\nexcept ValueError as e:\n    if 'not a `Buffer`' in str(e):\n        pass  # key belongs to a semaphore; nothing to deallocate\n    else:\n        raise","preventionTips":["Only deallocate keys returned by allocate_buffer","Keep buffer keys and semaphore IDs in disjoint namespaces"],"tags":["jax","pallas","mosaic","shared-memory","key-collision","interpret-mode"],"backgroundTag":"invalid-key-type","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}