diff --git a/modcc/error.hpp b/modcc/error.hpp
index e66fc45478faa8dde356e37b7e51d7b0460f000c..919d124884ce64b28a328e4bfd04b6df49e747fd 100644
--- a/modcc/error.hpp
+++ b/modcc/error.hpp
@@ -71,6 +71,3 @@ public:
 private:
     error_entry error_info_;
 };
-
-
-
diff --git a/modcc/expression.hpp b/modcc/expression.hpp
index da885630f2080290de61ca1b8c209f14282b0126..d369e7a99e9138aab7d80fc1b3da5a048d06842b 100644
--- a/modcc/expression.hpp
+++ b/modcc/expression.hpp
@@ -18,6 +18,7 @@
 class Visitor;
 
 class ARB_LIBMODCC_API Expression;
+struct ARB_LIBMODCC_API ErrorExpression;
 class ARB_LIBMODCC_API CallExpression;
 class ARB_LIBMODCC_API BlockExpression;
 class ARB_LIBMODCC_API IfExpression;
@@ -209,6 +210,20 @@ protected:
     scope_ptr scope_;
 };
 
+struct ARB_LIBMODCC_API ErrorExpression : public Expression {
+    explicit ErrorExpression(Location location): Expression(location)
+    {}
+
+    std::string to_string() const override {
+        return "Error" + error_string_;
+    }
+
+    void accept(Visitor *) override {
+        throw compiler_exception{"Attempted to visit error expression.", location()};
+    }
+};
+
+
 class ARB_LIBMODCC_API Symbol : public Expression {
 public :
     Symbol(Location loc, std::string name, symbolKind kind)
diff --git a/modcc/modcc.cpp b/modcc/modcc.cpp
index 6e9b51ba7fbe3478b2899d5c2eba5ef65a557340..3eea843b0c550f0dfc5a98537d479394fb9dadd5 100644
--- a/modcc/modcc.cpp
+++ b/modcc/modcc.cpp
@@ -25,12 +25,12 @@ using std::cerr;
 // Options and option parsing:
 
 int report_error(const std::string& message) {
-    cerr << red("error: ") << message << "\n";
+    cerr << red("error trace:\n") << message << "\n";
     return 1;
 }
 
 int report_ice(const std::string& message) {
-    cerr << red("internal compiler error: ") << message << "\n"
+    cerr << red("internal compiler error:\n") << message << "\n"
          << "\nPlease report this error to the modcc developers.\n";
     return 1;
 }
@@ -223,6 +223,7 @@ int main(int argc, char **argv) {
         emit_header("semantic analysis");
         m.semantic();
         if (m.has_warning()) {
+            cerr << yellow("Warnings:\n");
             cerr << m.warning_string() << "\n";
         }
         if (m.has_error()) {
diff --git a/modcc/module.cpp b/modcc/module.cpp
index 6d6a56a0dd1b980e0b486d0b48407d8135b8bddf..7dafa6ed0d65df27ada23dfb0f516a96e0478559 100644
--- a/modcc/module.cpp
+++ b/modcc/module.cpp
@@ -119,7 +119,7 @@ std::string Module::error_string() const {
     std::string str;
     for (const error_entry& entry: errors()) {
         if (!str.empty()) str += '\n';
-        str += red("error   ");
+        str += red("  * ");
         str += white(pprintf("%:% ", source_name(), entry.location));
         str += entry.message;
     }
@@ -130,7 +130,7 @@ std::string Module::warning_string() const {
     std::string str;
     for (auto& entry: warnings()) {
         if (!str.empty()) str += '\n';
-        str += purple("warning   ");
+        str += purple("  * ");
         str += white(pprintf("%:% ", source_name(), entry.location));
         str += entry.message;
     }
diff --git a/modcc/solvers.cpp b/modcc/solvers.cpp
index 1d31e55d8fe70e4573efed3390b0b389ebf477d0..23d89a41e12c713963014adfba3b9dbbfcae7905 100644
--- a/modcc/solvers.cpp
+++ b/modcc/solvers.cpp
@@ -41,7 +41,13 @@ void CnexpSolverVisitor::visit(AssignmentExpression *e) {
     }
 
     auto s = deriv->name();
+
     linear_test_result r = linear_test(rhs, dvars_);
+    if (r.has_error()) {
+        append_errors(r.errors());
+        error({"CNExp: Could not determine linearity, maybe use a different solver?", loc});
+        return;
+    }
 
     if (!r.monolinear(s)) {
         error({"System not diagonal linear for cnexp", loc});
@@ -52,7 +58,6 @@ void CnexpSolverVisitor::visit(AssignmentExpression *e) {
     if (!coef || is_zero(coef)) {
         // s' = b becomes s = s + b*dt; use b_ as a local variable for
         // the constant term b.
-
         auto local_b_term = make_unique_local_assign(scope, r.constant.get(), "b_");
         statements_.push_back(std::move(local_b_term.local_decl));
         statements_.push_back(std::move(local_b_term.assignment));
diff --git a/modcc/symdiff.cpp b/modcc/symdiff.cpp
index 4946a1b8108c4ce3f33a405a712be82269019c8e..1b4028eba54bd5254cec2da49fe217fbeaa7458f 100644
--- a/modcc/symdiff.cpp
+++ b/modcc/symdiff.cpp
@@ -562,7 +562,17 @@ ARB_LIBMODCC_API expression_ptr symbolic_pdiff(Expression* e, const std::string&
     SymPDiffVisitor pdiff_visitor(id);
     e->accept(&pdiff_visitor);
 
-    if (pdiff_visitor.has_error()) return nullptr;
+    if (pdiff_visitor.has_error()) {
+        std::string errors, sep = "";
+
+        for (const auto& error: pdiff_visitor.errors()) {
+            errors += sep + error.message;
+            sep = "\n";
+        }
+        auto res = std::make_unique<ErrorExpression>(e->location());
+        res->error(errors);
+        return res;
+    }
 
     return constant_simplify(pdiff_visitor.result());
 }
@@ -666,17 +676,20 @@ ARB_LIBMODCC_API linear_test_result linear_test(Expression* e, const std::vector
     result.constant = e->clone();
     for (const auto& id: vars) {
         auto coef = symbolic_pdiff(e, id);
-        if (!coef) {
-            return linear_test_result{};
+        if (coef->has_error()) {
+            auto res = linear_test_result{};
+            res.error({coef->error_message(), loc});
+            return res;
         }
+        if (!coef) return linear_test_result{};
         if (!is_zero(coef)) result.coef[id] = std::move(coef);
-
         result.constant = substitute(result.constant, id, zero());
     }
 
     ConstantSimplifyVisitor csimp_visitor;
     result.constant->accept(&csimp_visitor);
     result.constant = csimp_visitor.result();
+    if (result.constant.get() == nullptr) throw compiler_exception{"Linear test: simplification of the constant term failed.", loc};
 
     // linearity test: take second order derivatives, test against zero.
     result.is_linear = true;
diff --git a/modcc/symdiff.hpp b/modcc/symdiff.hpp
index cb58ffae803c36d37a4bef86e2b6974b9424badf..b43874898138ece6abe9d389302e81d2210b1908 100644
--- a/modcc/symdiff.hpp
+++ b/modcc/symdiff.hpp
@@ -81,7 +81,7 @@ inline expression_ptr substitute(const expression_ptr& e, const substitute_map&
 
 // Linearity testing
 
-struct linear_test_result {
+struct linear_test_result: public error_stack {
     bool is_linear = false;
     bool is_homogeneous = false;
     expression_ptr constant;
diff --git a/test/unit-modcc/mod_files/bug-1893-bad.mod b/test/unit-modcc/mod_files/bug-1893-bad.mod
new file mode 100644
index 0000000000000000000000000000000000000000..fde7f171b32138e6f1979897bff0fcc27fa4ac08
--- /dev/null
+++ b/test/unit-modcc/mod_files/bug-1893-bad.mod
@@ -0,0 +1,28 @@
+NEURON {
+    POINT_PROCESS bug_1893
+}
+
+INITIAL {
+    c = 0
+    rho = 0
+    theta_p = 0
+}
+
+STATE {
+    c
+    rho
+    theta_p
+}
+
+PARAMETER {
+    tau_c = 150 (ms)
+}
+
+BREAKPOINT {
+    SOLVE state METHOD cnexp
+}
+
+DERIVATIVE state {
+    c' = -c/tau_c
+    rho' = (c - theta_p) > 0
+}
diff --git a/test/unit-modcc/mod_files/bug-1893.mod b/test/unit-modcc/mod_files/bug-1893.mod
new file mode 100644
index 0000000000000000000000000000000000000000..14cfd5e5dc3fba55d97516e3ec1b72b2a8d5bc70
--- /dev/null
+++ b/test/unit-modcc/mod_files/bug-1893.mod
@@ -0,0 +1,28 @@
+NEURON {
+    POINT_PROCESS bug_1893
+}
+
+INITIAL {
+    c = 0
+    rho = 0
+    theta_p = 0
+}
+
+STATE {
+    c
+    rho
+    theta_p
+}
+
+PARAMETER {
+    tau_c = 150 (ms)
+}
+
+BREAKPOINT {
+    SOLVE state METHOD sparse
+}
+
+DERIVATIVE state {
+    c' = -c/tau_c
+    rho' = (c - theta_p) > 0
+}
diff --git a/test/unit-modcc/test_module.cpp b/test/unit-modcc/test_module.cpp
index 34ff5b4d9ba4d129410d4b9310a4e847dca7368f..9e9a1db0a78ec14848a48f6aa8740e571db3583f 100644
--- a/test/unit-modcc/test_module.cpp
+++ b/test/unit-modcc/test_module.cpp
@@ -122,3 +122,24 @@ TEST(Module, read_write_ion) {
     EXPECT_TRUE(p.parse());
     EXPECT_TRUE(m.semantic());
 }
+
+// Regression test in #1893 we found that the solver segfaults when handed a
+// naked comparison statement.
+TEST(Module, solver_bug_1893) {
+    {
+        Module m(io::read_all(DATADIR "/mod_files/bug-1893.mod"), "bug-1893.mod");
+        EXPECT_NE(m.buffer().size(), 0);
+
+        Parser p(m, false);
+        EXPECT_TRUE(p.parse());
+        EXPECT_TRUE(m.semantic());
+    }
+    {
+        Module m(io::read_all(DATADIR "/mod_files/bug-1893-bad.mod"), "bug-1893.mod");
+        EXPECT_NE(m.buffer().size(), 0);
+
+        Parser p(m, false);
+        EXPECT_TRUE(p.parse());
+        EXPECT_FALSE(m.semantic());
+    }
+}