jax-ml/jax · error · nb::value_error

Argument to get_c_api_topology contained a null pointer.

Error message

Argument to get_c_api_topology contained a null pointer.

What it means

Even a correctly named capsule must carry a non-null pointer; a null payload cannot be dereferenced as PJRT_Api*, so get_c_api_topology rejects it explicitly.

Source

Thrown at jaxlib/jax.cc:611

  // standard registration.
  m.def("get_default_c_api_topology",
        [](std::string platform_name, std::string topology_name,
           const absl::flat_hash_map<std::string, xla::PjRtValueType>& options)
            -> std::shared_ptr<xla::ifrt::Topology> {
          return std::make_shared<xla::ifrt::PjRtTopology>(xla::ValueOrThrow(
              xla::GetCApiTopology(platform_name, topology_name, options)));
        });
  m.def("get_c_api_topology",
        [](nb::capsule c_api, std::string topology_name,
           const absl::flat_hash_map<std::string, xla::PjRtValueType>& options)
            -> std::shared_ptr<xla::ifrt::Topology> {
          if (c_api.name() == nullptr ||
              std::string_view(c_api.name()) != "pjrt_c_api") {
            throw nb::value_error(
                "Argument to get_c_api_topology was not a pjrt_c_api capsule.");
          }
          if (c_api.data() == nullptr) {
            throw nb::value_error(
                "Argument to get_c_api_topology contained a null pointer.");
          }
          return std::make_shared<xla::ifrt::PjRtTopology>(xla::ValueOrThrow(
              xla::GetCApiTopology(static_cast<const PJRT_Api*>(c_api.data()),
                                   topology_name, options)));
        });
  m.def("get_topology_for_devices",
        [](const std::vector<nb_class_ptr<PyDevice>>& py_devices) {
          if (py_devices.empty()) {
            throw nb::value_error(
                "get_topology_for_devices requires >= 1 devices.");
          }
          auto client = py_devices[0]->client();
          absl::InlinedVector<xla::ifrt::Device*, 1> ifrt_devices;
          ifrt_devices.reserve(py_devices.size());
          for (const auto& py_device : py_devices) {
            if (py_device->client().get() != client.get()) {
              throw nb::value_error(

View on GitHub (pinned to 1e1c6a8fc0)

Solutions

  1. Ensure the plugin loaded successfully before distributing its capsule
  2. Re-obtain the capsule from load_pjrt_plugin and check it is non-null

Example fix

# before
assert cap is not None
jaxlib.get_c_api_topology(cap, 'topo')
# after
cap = jaxlib.load_pjrt_plugin(p, library_path)
assert cap is not None and ctypes.cast(cap, ctypes.c_void_p).value
jaxlib.get_c_api_topology(cap, 'topo')
Defensive patterns

Strategy: validation

Validate before calling

import ctypes
assert ctypes.cast(c_api, ctypes.c_void_p).value is not None

Prevention

When it happens

Trigger: Passing a capsule constructed as nb::capsule(nullptr, 'pjrt_c_api') or a capsule whose pointed-to API was already freed.

Common situations: Plugins that return empty capsules on failed initialization; use-after-free of a plugin API handle.

Related errors


AI-assisted analysis of jax-ml/jax@1e1c6a8fc0 (2026-08-27). Data as JSON: /api/errors/9e910a8cf47e7f52. Report an issue: GitHub.