{"record":{"id":"be27e701703e9b76","repo":"jax-ml/jax","slug":"cannot-name-on-a-non-semaphore-ref-sem-aval","errorCode":null,"errorMessage":"Cannot {name} on a non-semaphore Ref: {sem_aval}","messagePattern":"Cannot (.+?) on a non-semaphore Ref: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/pallas/primitives.py","lineNumber":890,"sourceCode":"\n\nclass DeviceIdType(enum.Enum):\n  MESH = \"mesh\"\n  LOGICAL = \"logical\"\n\n\ndef check_sem_avals(\n    sem_aval, sem_transforms_avals, name, allowed_semaphore_types=None\n):\n  if allowed_semaphore_types is None:\n    allowed_semaphore_types = {\n        pallas_core.semaphore,\n        pallas_core.barrier_semaphore,\n        # For interpret mode.\n        pallas_core.SEMAPHORE_INTERPRET_DTYPE,\n    }\n  if not isinstance(sem_aval, state.AbstractRef):\n    raise ValueError(f\"Cannot {name} on a non-semaphore Ref: {sem_aval}\")\n  sem_shape = sem_aval.shape\n  if sem_transforms_avals:\n    sem_shape = sem_transforms_avals[-1].get_indexer_shape()\n  if sem_shape:\n    raise ValueError(f\"Cannot {name} on a non-()-shaped semaphore: {sem_shape}\")\n  sem_dtype = sem_aval.dtype\n  if not any(\n      jnp.issubdtype(sem_dtype, sem_type)\n      for sem_type in allowed_semaphore_types\n  ):\n    raise ValueError(\n        f\"Must {name} semaphores of the following types:\"\n        f\" {allowed_semaphore_types}. Got {sem_dtype}.\"\n    )\n\n\ndef _transform_semaphore(ref_value, transforms, ref_aval):\n  \"\"\"Helper function for indexing into a semaphore during state_discharge.\"\"\"","sourceCodeStart":872,"sourceCodeEnd":908,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/pallas/primitives.py#L872-L908","documentation":"Semaphore operations (signal, wait, read) in Pallas require the target to be a state.AbstractRef holding a semaphore. This error fires when the value passed is not a Ref at all (e.g., a plain array or a different reference type).","triggerScenarios":"Passing a non-Ref value (jnp array, TracedArray, or a Ref of non-semaphore abstraction) to semaphore_signal / semaphore_wait / semaphore_read.","commonSituations":"Forgetting to allocate the semaphore via pallas state and passing its current value instead of the Ref; unwrapping refs too early in kernel code.","solutions":["Allocate the semaphore with the Pallas allocation API and pass the Ref itself, not a read value","Check that the argument is a state.Ref (isinstance(ref, state.Ref)) before calling semaphore ops"],"exampleFix":"// before\nsemaphore_wait(sem[...], 1)  # passed value not Ref\n// after\nsemaphore_wait(sem, 1)  # pass the Ref","handlingStrategy":"type-guard","validationCode":"from jax._src import state\nassert isinstance(sem, state.Ref), f\"expected a Ref semaphore, got {type(sem)}\"","typeGuard":"def is_semaphore_ref(sem) -> bool:\n    from jax._src import state\n    return isinstance(sem, state.Ref)","tryCatchPattern":"try:\n    semaphore_wait(sem, 1)\nexcept ValueError as e:\n    if \"non-semaphore Ref\" in str(e):\n        raise TypeError(\"pass the semaphore Ref, not its value\") from e\n    raise","preventionTips":["Always pass the Ref itself to semaphore ops","Wrap semaphore helpers with Ref assertions in tests"],"tags":["pallas","semaphore","type-validation","jax"],"backgroundTag":"invalid-argument-type","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}