diff --git a/arbor/fvm_layout.cpp b/arbor/fvm_layout.cpp
index 3261726fec562f8f7f0fa87132b327538ffb6c92..d2ee99ce301ddf0c16f93dcba030223c3e69afc1 100644
--- a/arbor/fvm_layout.cpp
+++ b/arbor/fvm_layout.cpp
@@ -858,14 +858,17 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
         const std::string& name = entry.first;
         mechanism_info info = catalogue[name];
 
-        std::vector<double> param_dflt;
         fvm_mechanism_config config;
-        config.kind = arb_mechanism_kind_density;
+        if (info.kind != arb_mechanism_kind_density) {
+            throw cable_cell_error("expected density mechanism, got " +name +" which has " +arb_mechsnism_kind_str(info.kind));
+        }
+        config.kind = info.kind;
 
         std::vector<std::string> param_names;
         assign(param_names, util::keys(info.parameters));
         sort(param_names);
 
+        std::vector<double> param_dflt;
         std::size_t n_param = param_names.size();
         param_dflt.reserve(n_param);
         config.param_values.reserve(n_param);
@@ -963,6 +966,10 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
         const std::string& name = entry.first;
         mechanism_info info = catalogue[name];
 
+        if (info.kind != arb_mechanism_kind_point) {
+            throw cable_cell_error("expected point mechanism, got " +name +" which has " +arb_mechsnism_kind_str(info.kind));
+        }
+
         post_events |= info.post_events;
         std::size_t n_param = info.parameters.size();
         std::size_t n_inst = entry.second.size();
@@ -1044,7 +1051,7 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
         bool coalesce = catalogue[name].linear && gprop.coalesce_synapses;
 
         fvm_mechanism_config config;
-        config.kind = arb_mechanism_kind_point;
+        config.kind = info.kind;
         for (auto& kv: info.parameters) {
             config.param_values.emplace_back(kv.first, std::vector<value_type>{});
             if (!coalesce) {
@@ -1210,6 +1217,10 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
         {
             const mechanism_desc& revpot = *maybe_revpot;
             mechanism_info info = catalogue[revpot.name()];
+            if (info.kind != arb_mechanism_kind_reversal_potential) {
+                throw cable_cell_error("expected reversal potential mechanism for ion " +ion +", got "+ revpot.name() +" which has " +arb_mechsnism_kind_str(info.kind));
+            }
+
             verify_mechanism(info, revpot);
             revpot_specified.insert(ion);
 
@@ -1248,7 +1259,7 @@ fvm_mechanism_data fvm_build_mechanism_data(const cable_cell_global_properties&
                 }
                 else {
                     fvm_mechanism_config config;
-                    config.kind = arb_mechanism_kind_reversal_potential;
+                    config.kind = info.kind;
                     config.cv = M.ions[ion].cv;
                     config.norm_area.assign(config.cv.size(), 1.);
 
diff --git a/arbor/include/arbor/mechanism_abi.h b/arbor/include/arbor/mechanism_abi.h
index ce85067fbb15afd70c43329db8adb197e372c533..83770e2e4be45fb7b160332bd66f75ea5e8bf5b5 100644
--- a/arbor/include/arbor/mechanism_abi.h
+++ b/arbor/include/arbor/mechanism_abi.h
@@ -27,6 +27,15 @@ typedef uint32_t arb_backend_kind;
 #define arb_backend_kind_cpu 1
 #define arb_backend_kind_gpu 2
 
+inline const char* arb_mechsnism_kind_str(const arb_mechanism_kind& mech) {
+    switch (mech) {
+        case arb_mechanism_kind_density: return "density mechanism kind";
+        case arb_mechanism_kind_point:   return "point mechanism kind";
+        case arb_mechanism_kind_reversal_potential: return "reversal potential mechanism kind";
+        default: return "unknown mechanism kind";
+    }
+}
+
 // Ion state variables; view into shared_state
 typedef struct arb_ion_state {
     arb_value_type* current_density;
diff --git a/arbor/include/arbor/mechinfo.hpp b/arbor/include/arbor/mechinfo.hpp
index 3e4ff24b81f9ec5c87ee900bf52a1d391e41ceb9..904fa90d8ca103934bffdad261abc558fb7c5d40 100644
--- a/arbor/include/arbor/mechinfo.hpp
+++ b/arbor/include/arbor/mechinfo.hpp
@@ -58,6 +58,9 @@ struct mechanism_info {
     mechanism_info(const arb_mechanism_type&);
     mechanism_info() = default;
 
+    // Mechanism kind
+    arb_mechanism_kind kind;
+
     // Global fields have one value common to an instance of a mechanism, are
     // constant in time and set at instantiation.
     std::unordered_map<std::string, mechanism_field_spec> globals;
diff --git a/arbor/mechinfo.cpp b/arbor/mechinfo.cpp
index abfe6c978e237dcf7b25b42ef53c2233b90ab95b..341568a78c3a6b3d5aa42617945a0023674fc973 100644
--- a/arbor/mechinfo.cpp
+++ b/arbor/mechinfo.cpp
@@ -4,6 +4,7 @@
 
 namespace arb {
 mechanism_info::mechanism_info(const arb_mechanism_type& m) {
+    kind = m.kind;
     post_events = m.has_post_events;
     linear      = m.is_linear;
     fingerprint = m.fingerprint;
diff --git a/doc/python/mechanisms.rst b/doc/python/mechanisms.rst
index 54c6a32efa401a12391a42e14340e4b93c057165..cb19925fcc711abec7d000719d0413153d4c008c 100644
--- a/doc/python/mechanisms.rst
+++ b/doc/python/mechanisms.rst
@@ -138,6 +138,11 @@ mechanism that is to be painted or placed on the cable cell.
         print(mech.parameters['tau'].default)
         # 2.0
 
+    .. py:attribute:: kind
+        :type: string
+
+        String representation of the kind of the mechanism: density, point or reversal potential.
+
     .. py:attribute:: globals
         :type: dict[str, mechanism_field]
 
@@ -163,6 +168,11 @@ mechanism that is to be painted or placed on the cable cell.
 
         True if a synapse mechanism has linear current contributions so that multiple instances on the same :term:`control volume` can be coalesced.
 
+    .. py:attribute:: post_events
+        :type: bool
+
+        True if a synapse mechanism has a `POST_EVENT` procedure defined.
+
 
 .. py:class:: ion_dependency
 
diff --git a/python/mechanism.cpp b/python/mechanism.cpp
index 2a27eccbcdfbb50dcdf295b719fdc3d14b22f2cd..16f9f25e8388f36135b79a2a9fccab956e1112e6 100644
--- a/python/mechanism.cpp
+++ b/python/mechanism.cpp
@@ -96,6 +96,12 @@ void register_mechanisms(pybind11::module& m) {
             "Ion dependencies.")
         .def_readonly("linear", &arb::mechanism_info::linear,
             "True if a synapse mechanism has linear current contributions so that multiple instances on the same compartment can be coalesced.")
+        .def_readonly("post_events", &arb::mechanism_info::post_events,
+            "True if a synapse mechanism has a `POST_EVENT` procedure defined.")
+        .def_property_readonly("kind",
+                [](const arb::mechanism_info& info) {
+                    return arb_mechsnism_kind_str(info.kind);
+                }, "String representation of the kind of the mechanism.")
         .def("__repr__",
                 [](const arb::mechanism_info& inf) {
                     return util::pprintf("(arbor.mechanism_info)"); })
diff --git a/test/unit/test_fvm_layout.cpp b/test/unit/test_fvm_layout.cpp
index 6d4e3a5a98b82b4a00473b486ece78759c00cdd0..981b291a064c42fb6b85e8e6209d715c37929381 100644
--- a/test/unit/test_fvm_layout.cpp
+++ b/test/unit/test_fvm_layout.cpp
@@ -129,6 +129,31 @@ namespace {
     }
 } // namespace
 
+template<typename P>
+void check_compatible_mechanism_failure(cable_cell_global_properties gprop, P painter) {
+    auto system = two_cell_system();
+
+    painter(system);
+
+    auto cells = system.cells();
+    check_two_cell_system(cells);
+    fvm_cv_discretization D = fvm_cv_discretize(cells, gprop.default_parameters);
+
+    EXPECT_THROW(fvm_build_mechanism_data(gprop, cells, D), arb::cable_cell_error);
+}
+
+TEST(fvm_layout, compatible_mechanisms) {
+    cable_cell_global_properties gprop;
+    gprop.default_parameters = neuron_parameter_defaults;
+
+    check_compatible_mechanism_failure(gprop, [](auto& sys) {sys.descriptions[0].decorations.place(sys.builders[0].location({1, 0.4}), "hh", "syn0"); });
+    check_compatible_mechanism_failure(gprop, [](auto& sys) {sys.descriptions[1].decorations.paint(sys.builders[1].cable(mcable{0}), "expsyn"); });
+    check_compatible_mechanism_failure(gprop, [](auto& sys) {sys.descriptions[0].decorations.set_default(ion_reversal_potential_method{"na", "expsyn"}); });
+
+    gprop.default_parameters.reversal_potential_method["na"] = "pas";
+    check_compatible_mechanism_failure(gprop, [](auto& sys) {});
+}
+
 TEST(fvm_layout, mech_index) {
     auto system = two_cell_system();
     auto& descriptions = system.descriptions;