Merge "Add casadi generator to symengine code"
diff --git a/aos/analysis/py_log_reader.cc b/aos/analysis/py_log_reader.cc
index 340140c..c190acb 100644
--- a/aos/analysis/py_log_reader.cc
+++ b/aos/analysis/py_log_reader.cc
@@ -111,7 +111,8 @@
     return -1;
   }
 
-  LogReaderTools *tools = CHECK_NOTNULL(self->tools);
+  LogReaderTools *tools = self->tools;
+  CHECK(tools != nullptr);
   tools->reader = std::make_unique<aos::logger::LogReader>(log_file_name);
   tools->reader->Register();
 
@@ -140,7 +141,8 @@
     return nullptr;
   }
 
-  LogReaderTools *tools = CHECK_NOTNULL(self->tools);
+  LogReaderTools *tools = self->tools;
+  CHECK(tools != nullptr);
 
   if (!tools->processed) {
     PyErr_SetString(PyExc_RuntimeError,
@@ -188,7 +190,8 @@
     return nullptr;
   }
 
-  LogReaderTools *tools = CHECK_NOTNULL(self->tools);
+  LogReaderTools *tools = self->tools;
+  CHECK(tools != nullptr);
 
   if (tools->processed) {
     PyErr_SetString(PyExc_RuntimeError,
@@ -217,7 +220,8 @@
 
 static PyObject *LogReader_process(LogReaderType *self,
                                    PyObject *Py_UNUSED(ignored)) {
-  LogReaderTools *tools = CHECK_NOTNULL(self->tools);
+  LogReaderTools *tools = self->tools;
+  CHECK(tools != nullptr);
 
   if (tools->processed) {
     PyErr_SetString(PyExc_RuntimeError, "process() may only be called once.");
@@ -233,7 +237,8 @@
 
 static PyObject *LogReader_configuration(LogReaderType *self,
                                          PyObject *Py_UNUSED(ignored)) {
-  LogReaderTools *tools = CHECK_NOTNULL(self->tools);
+  LogReaderTools *tools = self->tools;
+  CHECK(tools != nullptr);
 
   // I have no clue if the Configuration that we get from the log reader is in a
   // contiguous chunk of memory, and I'm too lazy to either figure it out or
diff --git a/aos/configuration.cc b/aos/configuration.cc
index cfc53a5..3b52e0c 100644
--- a/aos/configuration.cc
+++ b/aos/configuration.cc
@@ -1135,9 +1135,11 @@
     const flatbuffers::Vector<flatbuffers::Offset<aos::Map>> *maps,
     std::string_view type, const Node *node, std::set<std::string> *names) {
   for (const Map *map : *maps) {
-    CHECK_NOTNULL(map);
-    const Channel *const match = CHECK_NOTNULL(map->match());
-    const Channel *const rename = CHECK_NOTNULL(map->rename());
+    CHECK(map != nullptr);
+    const Channel *const match = map->match();
+    CHECK(match != nullptr);
+    const Channel *const rename = map->rename();
+    CHECK(rename != nullptr);
 
     // Handle type specific maps.
     const flatbuffers::String *const match_type_string = match->type();
@@ -1728,8 +1730,8 @@
   }
   CHECK(channel->has_source_node()) << FlatbufferToJson(channel);
   CHECK(node->has_name()) << FlatbufferToJson(node);
-  return (CHECK_NOTNULL(channel)->source_node()->string_view() ==
-          node->name()->string_view());
+  CHECK(channel != nullptr);
+  return (channel->source_node()->string_view() == node->name()->string_view());
 }
 
 bool ChannelIsReadableOnNode(const Channel *channel, const Node *node) {
@@ -1776,8 +1778,8 @@
     LOG(FATAL) << "Unsupported logging configuration in a single node world: "
                << CleanedChannelToString(channel);
   }
-  return ChannelMessageIsLoggedOnNode(
-      channel, CHECK_NOTNULL(node)->name()->string_view());
+  CHECK(node != nullptr);
+  return ChannelMessageIsLoggedOnNode(channel, node->name()->string_view());
 }
 
 bool ChannelMessageIsLoggedOnNode(const Channel *channel,
@@ -2116,7 +2118,7 @@
   flatbuffers::FlatBufferBuilder fbb;
   std::vector<flatbuffers::Offset<Channel>> new_channels_vec;
   for (const auto &channel : *configuration.channels()) {
-    CHECK_NOTNULL(channel);
+    CHECK(channel != nullptr);
     if (should_include_channel(*channel)) {
       new_channels_vec.push_back(RecursiveCopyFlatBuffer(channel, &fbb));
     }
diff --git a/aos/configuration_test.cc b/aos/configuration_test.cc
index da96402..d980dad 100644
--- a/aos/configuration_test.cc
+++ b/aos/configuration_test.cc
@@ -979,14 +979,16 @@
 TEST_F(ConfigurationTest, GetNodeFromHostname) {
   FlatbufferDetachedBuffer<Configuration> config =
       ReadConfig(ArtifactPath("aos/testdata/good_multinode.json"));
-  EXPECT_EQ("pi1",
-            CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "raspberrypi"))
-                ->name()
-                ->string_view());
-  EXPECT_EQ("pi2", CHECK_NOTNULL(
-                       GetNodeFromHostname(&config.message(), "raspberrypi2"))
-                       ->name()
-                       ->string_view());
+  {
+    const Node *pi1 = GetNodeFromHostname(&config.message(), "raspberrypi");
+    ASSERT_TRUE(pi1 != nullptr);
+    EXPECT_EQ("pi1", pi1->name()->string_view());
+  }
+  {
+    const Node *pi2 = GetNodeFromHostname(&config.message(), "raspberrypi2");
+    ASSERT_TRUE(pi2 != nullptr);
+    EXPECT_EQ("pi2", pi2->name()->string_view());
+  }
   EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "raspberrypi3"));
   EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "localhost"));
   EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "3"));
@@ -995,22 +997,26 @@
 TEST_F(ConfigurationTest, GetNodeFromHostnames) {
   FlatbufferDetachedBuffer<Configuration> config =
       ReadConfig(ArtifactPath("aos/testdata/good_multinode_hostnames.json"));
-  EXPECT_EQ("pi1",
-            CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "raspberrypi"))
-                ->name()
-                ->string_view());
-  EXPECT_EQ("pi2", CHECK_NOTNULL(
-                       GetNodeFromHostname(&config.message(), "raspberrypi2"))
-                       ->name()
-                       ->string_view());
-  EXPECT_EQ("pi2", CHECK_NOTNULL(
-                       GetNodeFromHostname(&config.message(), "raspberrypi3"))
-                       ->name()
-                       ->string_view());
-  EXPECT_EQ("pi2",
-            CHECK_NOTNULL(GetNodeFromHostname(&config.message(), "other"))
-                ->name()
-                ->string_view());
+  {
+    const Node *pi1 = GetNodeFromHostname(&config.message(), "raspberrypi");
+    ASSERT_TRUE(pi1 != nullptr);
+    EXPECT_EQ("pi1", pi1->name()->string_view());
+  }
+  {
+    const Node *pi2 = GetNodeFromHostname(&config.message(), "raspberrypi2");
+    ASSERT_TRUE(pi2 != nullptr);
+    EXPECT_EQ("pi2", pi2->name()->string_view());
+  }
+  {
+    const Node *pi2 = GetNodeFromHostname(&config.message(), "raspberrypi3");
+    ASSERT_TRUE(pi2 != nullptr);
+    EXPECT_EQ("pi2", pi2->name()->string_view());
+  }
+  {
+    const Node *pi2 = GetNodeFromHostname(&config.message(), "other");
+    ASSERT_TRUE(pi2 != nullptr);
+    EXPECT_EQ("pi2", pi2->name()->string_view());
+  }
   EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "raspberrypi4"));
   EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "localhost"));
   EXPECT_EQ(nullptr, GetNodeFromHostname(&config.message(), "3"));
diff --git a/aos/containers/resizeable_buffer.h b/aos/containers/resizeable_buffer.h
index 664fa2f..1af888d 100644
--- a/aos/containers/resizeable_buffer.h
+++ b/aos/containers/resizeable_buffer.h
@@ -108,7 +108,9 @@
 
   void Allocate(size_t new_capacity) {
     void *const old = storage_.release();
-    storage_.reset(CHECK_NOTNULL(F::Realloc(old, capacity_, new_capacity)));
+    void *new_ptr = F::Realloc(old, capacity_, new_capacity);
+    CHECK(new_ptr != nullptr);
+    storage_.reset(new_ptr);
     capacity_ = new_capacity;
   }
 
diff --git a/aos/events/epoll.cc b/aos/events/epoll.cc
index 61c346e..d5f5162 100644
--- a/aos/events/epoll.cc
+++ b/aos/events/epoll.cc
@@ -193,7 +193,9 @@
 }
 
 void EPoll::SetEvents(int fd, uint32_t events) {
-  DoEpollCtl(CHECK_NOTNULL(GetEventData(fd)), events);
+  EventData *event_data;
+  CHECK((event_data = GetEventData(fd)) != nullptr);
+  DoEpollCtl(event_data, events);
 }
 
 // Removes fd from the event loop.
@@ -257,12 +259,14 @@
 }
 
 void EPoll::EnableEvents(int fd, uint32_t events) {
-  EventData *const event_data = CHECK_NOTNULL(GetEventData(fd));
+  EventData *const event_data = GetEventData(fd);
+  CHECK(event_data != nullptr);
   DoEpollCtl(event_data, event_data->events | events);
 }
 
 void EPoll::DisableEvents(int fd, uint32_t events) {
-  EventData *const event_data = CHECK_NOTNULL(GetEventData(fd));
+  EventData *const event_data = GetEventData(fd);
+  CHECK(event_data != nullptr);
   DoEpollCtl(event_data, event_data->events & ~events);
 }
 
diff --git a/aos/events/event_loop.h b/aos/events/event_loop.h
index 389ea08..c8cf487 100644
--- a/aos/events/event_loop.h
+++ b/aos/events/event_loop.h
@@ -265,7 +265,8 @@
   // Fetches the next message. Returns true if it fetched a new message.  This
   // method will only return messages sent after the Fetcher was created.
   bool FetchNext() {
-    const bool result = CHECK_NOTNULL(fetcher_)->FetchNext();
+    CHECK(fetcher_ != nullptr);
+    const bool result = fetcher_->FetchNext();
     if (result) {
       CheckChannelDataAlignment(fetcher_->context().data,
                                 fetcher_->context().size);
@@ -277,7 +278,8 @@
   // true.  The data and buffer_index are the only pieces of the Context which
   // are zeroed out.  The function must be valid.
   bool FetchNextIf(std::function<bool(const Context &)> fn) {
-    const bool result = CHECK_NOTNULL(fetcher_)->FetchNextIf(std::move(fn));
+    CHECK(fetcher_ != nullptr);
+    const bool result = fetcher_->FetchNextIf(std::move(fn));
     if (result) {
       CheckChannelDataAlignment(fetcher_->context().data,
                                 fetcher_->context().size);
@@ -289,7 +291,8 @@
   // This will return the latest message regardless of if it was sent before or
   // after the fetcher was created.
   bool Fetch() {
-    const bool result = CHECK_NOTNULL(fetcher_)->Fetch();
+    CHECK(fetcher_ != nullptr);
+    const bool result = fetcher_->Fetch();
     if (result) {
       CheckChannelDataAlignment(fetcher_->context().data,
                                 fetcher_->context().size);
@@ -301,7 +304,8 @@
   // new message. This will return the latest message regardless of if it was
   // sent before or after the fetcher was created.  The function must be valid.
   bool FetchIf(std::function<bool(const Context &)> fn) {
-    const bool result = CHECK_NOTNULL(fetcher_)->FetchIf(std::move(fn));
+    CHECK(fetcher_ != nullptr);
+    const bool result = fetcher_->FetchIf(std::move(fn));
     if (result) {
       CheckChannelDataAlignment(fetcher_->context().data,
                                 fetcher_->context().size);
@@ -312,18 +316,25 @@
   // Returns a pointer to the contained flatbuffer, or nullptr if there is no
   // available message.
   const T *get() const {
-    return CHECK_NOTNULL(fetcher_)->context().data != nullptr
+    CHECK(fetcher_ != nullptr);
+    return fetcher_->context().data != nullptr
                ? flatbuffers::GetRoot<T>(
                      reinterpret_cast<const char *>(fetcher_->context().data))
                : nullptr;
   }
 
   // Returns the channel this fetcher uses
-  const Channel *channel() const { return CHECK_NOTNULL(fetcher_)->channel(); }
+  const Channel *channel() const {
+    CHECK(fetcher_ != nullptr);
+    return fetcher_->channel();
+  }
 
   // Returns the context holding timestamps and other metadata about the
   // message.
-  const Context &context() const { return CHECK_NOTNULL(fetcher_)->context(); }
+  const Context &context() const {
+    CHECK(fetcher_ != nullptr);
+    return fetcher_->context();
+  }
 
   const T &operator*() const { return *get(); }
   const T *operator->() const { return get(); }
@@ -366,7 +377,9 @@
   class StaticBuilder {
    public:
     StaticBuilder(RawSender *sender, fbs::SpanAllocator *allocator)
-        : builder_(allocator), sender_(CHECK_NOTNULL(sender)) {}
+        : builder_(allocator), sender_(sender) {
+      CHECK(sender != nullptr);
+    }
     StaticBuilder(const StaticBuilder &) = delete;
     StaticBuilder(StaticBuilder &&) = default;
 
@@ -408,7 +421,8 @@
     Builder(RawSender *sender, ChannelPreallocatedAllocator *allocator)
         : fbb_(allocator->size(), allocator),
           allocator_(allocator),
-          sender_(CHECK_NOTNULL(sender)) {
+          sender_(sender) {
+      CHECK(sender != nullptr);
       CheckChannelDataAlignment(allocator->data(), allocator->size());
       fbb_.ForceDefaults(true);
     }
@@ -480,12 +494,16 @@
 
   // Equivalent to RawSender::CheckOk
   void CheckOk(const RawSender::Error err) {
-    CHECK_NOTNULL(sender_)->CheckOk(err);
+    CHECK(sender_ != nullptr);
+    sender_->CheckOk(err);
   };
 
   // Returns the name of the underlying queue, if valid.  You must check valid()
   // first.
-  const Channel *channel() const { return CHECK_NOTNULL(sender_)->channel(); }
+  const Channel *channel() const {
+    CHECK(sender_ != nullptr);
+    return sender_->channel();
+  }
 
   // Returns true if the Sender is a valid Sender. If you, e.g., are using
   // TryMakeSender, then you must check valid() before attempting to use the
@@ -496,19 +514,25 @@
 
   // Returns the time_points that the last message was sent at.
   aos::monotonic_clock::time_point monotonic_sent_time() const {
-    return CHECK_NOTNULL(sender_)->monotonic_sent_time();
+    CHECK(sender_ != nullptr);
+    return sender_->monotonic_sent_time();
   }
   aos::realtime_clock::time_point realtime_sent_time() const {
-    return CHECK_NOTNULL(sender_)->realtime_sent_time();
+    CHECK(sender_ != nullptr);
+    return sender_->realtime_sent_time();
   }
   // Returns the queue index that this was sent with.
   uint32_t sent_queue_index() const {
-    return CHECK_NOTNULL(sender_)->sent_queue_index();
+    CHECK(sender_ != nullptr);
+    return sender_->sent_queue_index();
   }
 
   // Returns the buffer index which MakeBuilder() will expose access to. This is
   // the buffer the caller can fill out.
-  int buffer_index() const { return CHECK_NOTNULL(sender_)->buffer_index(); }
+  int buffer_index() const {
+    CHECK(sender_ != nullptr);
+    return sender_->buffer_index();
+  }
 
   // Convenience function to build and send a message created from JSON
   // representation.
diff --git a/aos/events/logging/buffer_encoder_param_test.cc b/aos/events/logging/buffer_encoder_param_test.cc
index 7c9bb4b..f6bc3b6 100644
--- a/aos/events/logging/buffer_encoder_param_test.cc
+++ b/aos/events/logging/buffer_encoder_param_test.cc
@@ -2,6 +2,8 @@
 
 #include "gmock/gmock.h"
 
+#include "aos/testing/tmpdir.h"
+
 namespace aos::logger::testing {
 
 // Verifies that Clear affects the sizes as expected.
@@ -39,8 +41,8 @@
 // it comes back out the same.
 TEST_P(BufferEncoderTest, RoundTrip) {
   std::uniform_int_distribution<int> quantity_distribution(20, 60);
-  const char *const test_dir = CHECK_NOTNULL(getenv("TEST_TMPDIR"));
-  const std::string file_path = std::string(test_dir) + "/foo";
+  const std::string test_dir = aos::testing::TestTmpDir();
+  const std::string file_path = test_dir + "/foo";
 
   std::vector<std::vector<uint8_t>> encoded_buffers;
   {
diff --git a/aos/events/logging/buffer_encoder_test.cc b/aos/events/logging/buffer_encoder_test.cc
index 7dda300..127fb4f 100644
--- a/aos/events/logging/buffer_encoder_test.cc
+++ b/aos/events/logging/buffer_encoder_test.cc
@@ -9,6 +9,7 @@
 #include "gtest/gtest.h"
 
 #include "aos/events/logging/buffer_encoder_param_test.h"
+#include "aos/testing/tmpdir.h"
 
 namespace aos::logger::testing {
 
@@ -44,8 +45,7 @@
 TEST(DummyDecoderTest, ReadsIntoExactBuffer) {
   static const std::string kTestString{"Just some random words."};
 
-  const char *const test_dir = CHECK_NOTNULL(getenv("TEST_TMPDIR"));
-  const std::string file_path = std::string(test_dir) + "/foo";
+  const std::string file_path = aos::testing::TestTmpDir() + "/foo";
   std::ofstream(file_path, std::ios::binary) << kTestString;
 
   // Read the contents of the file into the buffer.
@@ -65,8 +65,7 @@
 TEST(DummyDecoderTest, ReadsIntoLargerBuffer) {
   static const std::string kTestString{"Just some random words."};
 
-  const char *const test_dir = CHECK_NOTNULL(getenv("TEST_TMPDIR"));
-  const std::string file_path = std::string(test_dir) + "/foo";
+  const std::string file_path = aos::testing::TestTmpDir() + "/foo";
   std::ofstream(file_path, std::ios::binary) << kTestString;
 
   DummyDecoder dummy_decoder(file_path.c_str());
@@ -84,8 +83,7 @@
 TEST(DummyDecoderTest, ReadsRepeatedlyIntoSmallerBuffer) {
   static const std::string kTestString{"Just some random words."};
 
-  const char *const test_dir = CHECK_NOTNULL(getenv("TEST_TMPDIR"));
-  const std::string file_path = std::string(test_dir) + "/foo";
+  const std::string file_path = aos::testing::TestTmpDir() + "/foo";
   std::ofstream(file_path, std::ios::binary) << kTestString;
 
   DummyDecoder dummy_decoder(file_path.c_str());
diff --git a/aos/events/logging/config_remapper.cc b/aos/events/logging/config_remapper.cc
index 21f45d5..088d393 100644
--- a/aos/events/logging/config_remapper.cc
+++ b/aos/events/logging/config_remapper.cc
@@ -263,7 +263,8 @@
   result.reserve(remapped_channels_.size());
   for (auto &pair : remapped_channels_) {
     const Channel *const original_channel =
-        CHECK_NOTNULL(original_configuration()->channels()->Get(pair.first));
+        original_configuration()->channels()->Get(pair.first);
+    CHECK(original_channel != nullptr);
 
     auto channel_iterator = std::lower_bound(
         remapped_configuration_->channels()->cbegin(),
@@ -472,9 +473,10 @@
 
   // Reconstruct the remapped channels.
   for (auto &pair : remapped_channels_) {
-    const Channel *const c = CHECK_NOTNULL(configuration::GetChannel(
+    const Channel *const c = configuration::GetChannel(
         base_config, original_configuration()->channels()->Get(pair.first), "",
-        nullptr));
+        nullptr);
+    CHECK(c != nullptr);
     channel_offsets.emplace_back(
         CopyChannel(c, pair.second.remapped_name, "", &fbb));
 
diff --git a/aos/events/logging/log_cat.cc b/aos/events/logging/log_cat.cc
index 31d12be..d7347be 100644
--- a/aos/events/logging/log_cat.cc
+++ b/aos/events/logging/log_cat.cc
@@ -245,7 +245,7 @@
         }
         VLOG(1) << "Listening on " << name << " " << type;
 
-        CHECK_NOTNULL(channel->schema());
+        CHECK(channel->schema() != nullptr);
         event_loop_->MakeRawWatcher(channel, [this, channel, start_time,
                                               end_time](
                                                  const aos::Context &context,
diff --git a/aos/events/logging/log_namer.cc b/aos/events/logging/log_namer.cc
index 6c88d89..c065f68 100644
--- a/aos/events/logging/log_namer.cc
+++ b/aos/events/logging/log_namer.cc
@@ -1065,7 +1065,7 @@
 
 void MultiNodeLogNamer::CloseWriter(
     std::unique_ptr<DetachedBufferWriter> *writer_pointer) {
-  CHECK_NOTNULL(writer_pointer);
+  CHECK(writer_pointer != nullptr);
   if (!(*writer_pointer)) {
     return;
   }
diff --git a/aos/events/logging/log_namer.h b/aos/events/logging/log_namer.h
index 08601f2..2c0982a 100644
--- a/aos/events/logging/log_namer.h
+++ b/aos/events/logging/log_namer.h
@@ -422,7 +422,7 @@
   bool ran_out_of_space() const {
     return accumulate_data_writers<bool>(
         ran_out_of_space_, [](bool x, const NewDataWriter &data_writer) {
-          CHECK_NOTNULL(data_writer.writer);
+          CHECK(data_writer.writer != nullptr);
           return x ||
                  (data_writer.writer && data_writer.writer->ran_out_of_space());
         });
@@ -435,7 +435,7 @@
   size_t maximum_total_bytes() const {
     return accumulate_data_writers<size_t>(
         0, [](size_t x, const NewDataWriter &data_writer) {
-          CHECK_NOTNULL(data_writer.writer);
+          CHECK(data_writer.writer != nullptr);
           return std::max(x, data_writer.writer->total_bytes());
         });
   }
@@ -452,7 +452,7 @@
     return accumulate_data_writers(
         max_write_time_,
         [](std::chrono::nanoseconds x, const NewDataWriter &data_writer) {
-          CHECK_NOTNULL(data_writer.writer);
+          CHECK(data_writer.writer != nullptr);
           return std::max(
               x, data_writer.writer->WriteStatistics()->max_write_time());
         });
@@ -462,7 +462,7 @@
         std::make_tuple(max_write_time_bytes_, max_write_time_),
         [](std::tuple<int, std::chrono::nanoseconds> x,
            const NewDataWriter &data_writer) {
-          CHECK_NOTNULL(data_writer.writer);
+          CHECK(data_writer.writer != nullptr);
           if (data_writer.writer->WriteStatistics()->max_write_time() >
               std::get<1>(x)) {
             return std::make_tuple(
@@ -477,7 +477,7 @@
         std::make_tuple(max_write_time_messages_, max_write_time_),
         [](std::tuple<int, std::chrono::nanoseconds> x,
            const NewDataWriter &data_writer) {
-          CHECK_NOTNULL(data_writer.writer);
+          CHECK(data_writer.writer != nullptr);
           if (data_writer.writer->WriteStatistics()->max_write_time() >
               std::get<1>(x)) {
             return std::make_tuple(
@@ -492,14 +492,14 @@
     return accumulate_data_writers(
         total_write_time_,
         [](std::chrono::nanoseconds x, const NewDataWriter &data_writer) {
-          CHECK_NOTNULL(data_writer.writer);
+          CHECK(data_writer.writer != nullptr);
           return x + data_writer.writer->WriteStatistics()->total_write_time();
         });
   }
   int total_write_count() const {
     return accumulate_data_writers(
         total_write_count_, [](int x, const NewDataWriter &data_writer) {
-          CHECK_NOTNULL(data_writer.writer);
+          CHECK(data_writer.writer != nullptr);
           return x + data_writer.writer->WriteStatistics()->total_write_count();
         });
   }
@@ -513,7 +513,7 @@
   int total_write_bytes() const {
     return accumulate_data_writers(
         total_write_bytes_, [](int x, const NewDataWriter &data_writer) {
-          CHECK_NOTNULL(data_writer.writer);
+          CHECK(data_writer.writer != nullptr);
           return x + data_writer.writer->WriteStatistics()->total_write_bytes();
         });
   }
@@ -522,7 +522,7 @@
     return accumulate_data_writers(
         total_encode_duration_,
         [](std::chrono::nanoseconds x, const NewDataWriter &data_writer) {
-          CHECK_NOTNULL(data_writer.writer);
+          CHECK(data_writer.writer != nullptr);
           return x +
                  data_writer.writer->WriteStatistics()->total_encode_duration();
         });
diff --git a/aos/events/logging/log_reader.cc b/aos/events/logging/log_reader.cc
index 192dade..81f8466 100644
--- a/aos/events/logging/log_reader.cc
+++ b/aos/events/logging/log_reader.cc
@@ -196,7 +196,7 @@
   {
     // Log files container validates that log files shared the same config.
     const Configuration *config = log_files_.config().get();
-    CHECK_NOTNULL(config);
+    CHECK(config != nullptr);
   }
 
   if (replay_channels_ != nullptr) {
@@ -386,7 +386,7 @@
 std::vector<
     std::pair<const aos::Channel *, NodeEventLoopFactory::ExclusiveSenders>>
 LogReader::State::NonExclusiveChannels() {
-  CHECK_NOTNULL(node_event_loop_factory_);
+  CHECK(node_event_loop_factory_ != nullptr);
   const aos::Configuration *config = node_event_loop_factory_->configuration();
   std::vector<
       std::pair<const aos::Channel *, NodeEventLoopFactory::ExclusiveSenders>>
@@ -1423,10 +1423,11 @@
 
   if (remote_timestamp_senders_[timestamped_message.channel_index] != nullptr) {
     State *source_state =
-        CHECK_NOTNULL(channel_source_state_[timestamped_message.channel_index]);
-    std::vector<ContiguousSentTimestamp> *queue_index_map = CHECK_NOTNULL(
-        source_state->queue_index_map_[timestamped_message.channel_index]
-            .get());
+        channel_source_state_[timestamped_message.channel_index];
+    CHECK(source_state != nullptr);
+    std::vector<ContiguousSentTimestamp> *queue_index_map =
+        source_state->queue_index_map_[timestamped_message.channel_index].get();
+    CHECK(queue_index_map != nullptr);
 
     struct SentTimestamp {
       monotonic_clock::time_point monotonic_event_time;
@@ -1495,15 +1496,13 @@
     // Sanity check that we are using consistent boot uuids.
     State *source_state =
         channel_source_state_[timestamped_message.channel_index];
+    CHECK(source_state != nullptr);
+    CHECK(source_state->event_loop_ != nullptr);
     CHECK_EQ(multinode_filters_->boot_uuid(
                  configuration::GetNodeIndex(event_loop_->configuration(),
                                              source_state->node()),
                  timestamped_message.monotonic_remote_time.boot),
-             CHECK_NOTNULL(
-                 CHECK_NOTNULL(
-                     channel_source_state_[timestamped_message.channel_index])
-                     ->event_loop_)
-                 ->boot_uuid());
+             source_state->event_loop_->boot_uuid());
   }
 
   SharedSpan to_send;
@@ -1529,20 +1528,23 @@
 
   // Send!  Use the replayed queue index here instead of the logged queue index
   // for the remote queue index.  This makes re-logging work.
+  const UUID boot_uuid = [&]() -> UUID {
+    if (channel_source_state_[timestamped_message.channel_index] != nullptr) {
+      CHECK(multinode_filters_ != nullptr);
+      return multinode_filters_->boot_uuid(
+          configuration::GetNodeIndex(
+              event_loop_->configuration(),
+              channel_source_state_[timestamped_message.channel_index]->node()),
+          timestamped_message.monotonic_remote_time.boot);
+    } else {
+      return event_loop_->boot_uuid();
+    }
+  }();
   const RawSender::Error err = sender->Send(
       std::move(to_send), timestamped_message.monotonic_remote_time.time,
       timestamped_message.realtime_remote_time,
       timestamped_message.monotonic_remote_transmit_time.time,
-      remote_queue_index,
-      (channel_source_state_[timestamped_message.channel_index] != nullptr
-           ? CHECK_NOTNULL(multinode_filters_)
-                 ->boot_uuid(configuration::GetNodeIndex(
-                                 event_loop_->configuration(),
-                                 channel_source_state_[timestamped_message
-                                                           .channel_index]
-                                     ->node()),
-                             timestamped_message.monotonic_remote_time.boot)
-           : event_loop_->boot_uuid()));
+      remote_queue_index, boot_uuid);
   if (err != RawSender::Error::kOk) return false;
   if (monotonic_start_time(timestamped_message.monotonic_event_time.boot) <=
       timestamped_message.monotonic_event_time.time) {
@@ -1601,7 +1603,8 @@
     // that the timestamps correspond to. This code, as written, also doesn't
     // correctly handle a non-zero clock_offset for the *_remote_time fields.
     State *source_state =
-        CHECK_NOTNULL(channel_source_state_[timestamped_message.channel_index]);
+        channel_source_state_[timestamped_message.channel_index];
+    CHECK(source_state != nullptr);
 
     flatbuffers::FlatBufferBuilder fbb;
     fbb.ForceDefaults(true);
@@ -1655,14 +1658,14 @@
 
 void LogReader::RemoteMessageSender::ScheduleTimestamp() {
   if (remote_timestamps_.empty()) {
-    CHECK_NOTNULL(timer_);
+    CHECK(timer_ != nullptr);
     timer_->Disable();
     scheduled_time_ = monotonic_clock::min_time;
     return;
   }
 
   if (scheduled_time_ != remote_timestamps_.front().monotonic_timestamp_time) {
-    CHECK_NOTNULL(timer_);
+    CHECK(timer_ != nullptr);
     timer_->Schedule(remote_timestamps_.front().monotonic_timestamp_time);
     scheduled_time_ = remote_timestamps_.front().monotonic_timestamp_time;
     CHECK_GE(scheduled_time_, event_loop_->monotonic_now())
diff --git a/aos/events/logging/log_reader.h b/aos/events/logging/log_reader.h
index f25f1f6..85d4d2c 100644
--- a/aos/events/logging/log_reader.h
+++ b/aos/events/logging/log_reader.h
@@ -655,7 +655,7 @@
     }
 
     monotonic_clock::time_point monotonic_now() const {
-      CHECK_NOTNULL(event_loop_);
+      CHECK(event_loop_ != nullptr);
       return event_loop_->monotonic_now();
     }
 
diff --git a/aos/events/logging/log_stats.cc b/aos/events/logging/log_stats.cc
index c0540bf..a45a167 100644
--- a/aos/events/logging/log_stats.cc
+++ b/aos/events/logging/log_stats.cc
@@ -128,7 +128,10 @@
       : channel_(channel),
         config_(factory->configuration()),
         factory_(factory),
-        schema_(CHECK_NOTNULL(schema)),
+        schema_([&]() {
+          CHECK(schema != nullptr);
+          return schema;
+        }()),
         destination_node_(destination_node),
         flatbuffer_type_(schema) {
     // Multi-node channel
diff --git a/aos/events/logging/log_writer.cc b/aos/events/logging/log_writer.cc
index c00d216..42dbbb5 100644
--- a/aos/events/logging/log_writer.cc
+++ b/aos/events/logging/log_writer.cc
@@ -297,8 +297,9 @@
           log_namer_->MakeTimestampWriter(f.event_loop_channel);
     }
     if (f.wants_contents_writer) {
+      CHECK(f.timestamp_node != nullptr);
       f.contents_writer = log_namer_->MakeForwardedTimestampWriter(
-          f.event_loop_channel, CHECK_NOTNULL(f.timestamp_node));
+          f.event_loop_channel, f.timestamp_node);
     }
   }
 
@@ -426,8 +427,9 @@
           log_namer_->MakeTimestampWriter(f.event_loop_channel);
     }
     if (f.wants_contents_writer) {
+      CHECK(f.timestamp_node != nullptr);
       f.contents_writer = log_namer_->MakeForwardedTimestampWriter(
-          f.event_loop_channel, CHECK_NOTNULL(f.timestamp_node));
+          f.event_loop_channel, f.timestamp_node);
     }
 
     // Mark each channel with data as not written.  That triggers each channel
diff --git a/aos/events/logging/logfile_utils.cc b/aos/events/logging/logfile_utils.cc
index 30ed3d7..0d10a99 100644
--- a/aos/events/logging/logfile_utils.cc
+++ b/aos/events/logging/logfile_utils.cc
@@ -2442,7 +2442,7 @@
 
 Message TimestampMapper::MatchingMessageFor(const Message &message) {
   // Figure out what queue index we are looking for.
-  CHECK_NOTNULL(message.header);
+  CHECK(message.header != nullptr);
   CHECK(message.header->remote_queue_index.has_value());
   const BootQueueIndex remote_queue_index =
       BootQueueIndex{.boot = message.monotonic_remote_boot,
diff --git a/aos/events/logging/lzma_encoder_test.cc b/aos/events/logging/lzma_encoder_test.cc
index 60444d3..92b4f54 100644
--- a/aos/events/logging/lzma_encoder_test.cc
+++ b/aos/events/logging/lzma_encoder_test.cc
@@ -4,6 +4,7 @@
 #include "gtest/gtest.h"
 
 #include "aos/events/logging/buffer_encoder_param_test.h"
+#include "aos/testing/tmpdir.h"
 #include "aos/util/file.h"
 
 DECLARE_int32(lzma_threads);
@@ -62,8 +63,7 @@
 // corrupted.
 TEST_F(BufferEncoderBaseTest, CorruptedBuffer) {
   std::uniform_int_distribution<int> quantity_distribution(20, 60);
-  const char *const test_dir = CHECK_NOTNULL(getenv("TEST_TMPDIR"));
-  const std::string file_path = std::string(test_dir) + "/foo";
+  const std::string file_path = aos::testing::TestTmpDir() + "/foo";
 
   std::vector<std::vector<uint8_t>> encoded_buffers;
   {
diff --git a/aos/events/logging/snappy_encoder.cc b/aos/events/logging/snappy_encoder.cc
index 0160177..b1cd80e 100644
--- a/aos/events/logging/snappy_encoder.cc
+++ b/aos/events/logging/snappy_encoder.cc
@@ -127,7 +127,8 @@
 }
 
 const char *SnappyEncoder::DetachedBufferSource::Peek(size_t *length) {
-  *CHECK_NOTNULL(length) = data_.size() - index_into_first_buffer_;
+  CHECK(length != nullptr);
+  *length = data_.size() - index_into_first_buffer_;
   return reinterpret_cast<char *>(data_.data()) + index_into_first_buffer_;
 }
 
diff --git a/aos/events/shm_event_loop_test.cc b/aos/events/shm_event_loop_test.cc
index 2fbe735..aae8f15 100644
--- a/aos/events/shm_event_loop_test.cc
+++ b/aos/events/shm_event_loop_test.cc
@@ -17,13 +17,6 @@
 class ShmEventLoopTestFactory : public EventLoopTestFactory {
  public:
   ShmEventLoopTestFactory() {
-    // Put all the queue files in ${TEST_TMPDIR} if it is set, otherwise
-    // everything will be reusing /dev/shm when sharded.
-    char *test_tmpdir = getenv("TEST_TMPDIR");
-    if (test_tmpdir != nullptr) {
-      FLAGS_shm_base = std::string(test_tmpdir) + "/aos";
-    }
-
     // Clean up anything left there before.
     unlink((FLAGS_shm_base + "/test/aos.TestMessage.v7").c_str());
     unlink((FLAGS_shm_base + "/test1/aos.TestMessage.v7").c_str());
@@ -58,14 +51,19 @@
   }
 
   Result<void> Run() override {
-    return CHECK_NOTNULL(primary_event_loop_)->Run();
+    CHECK(primary_event_loop_ != nullptr);
+    return primary_event_loop_->Run();
   }
 
   std::unique_ptr<ExitHandle> MakeExitHandle() override {
-    return CHECK_NOTNULL(primary_event_loop_)->MakeExitHandle();
+    CHECK(primary_event_loop_ != nullptr);
+    return primary_event_loop_->MakeExitHandle();
   }
 
-  void Exit() override { CHECK_NOTNULL(primary_event_loop_)->Exit(); }
+  void Exit() override {
+    CHECK(primary_event_loop_ != nullptr);
+    primary_event_loop_->Exit();
+  }
 
   void SleepFor(::std::chrono::nanoseconds duration) override {
     ::std::this_thread::sleep_for(duration);
diff --git a/aos/events/simple_channel.cc b/aos/events/simple_channel.cc
index 00e30ba..51d9ef6 100644
--- a/aos/events/simple_channel.cc
+++ b/aos/events/simple_channel.cc
@@ -5,9 +5,15 @@
 
 namespace aos {
 
-SimpleChannel::SimpleChannel(const Channel *channel)
-    : name(CHECK_NOTNULL(CHECK_NOTNULL(channel)->name())->str()),
-      type(CHECK_NOTNULL(CHECK_NOTNULL(channel)->type())->str()) {}
+SimpleChannel::SimpleChannel(const Channel *channel) {
+  CHECK(channel != nullptr);
+  const flatbuffers::String *channel_name = channel->name();
+  CHECK(channel_name != nullptr);
+  name = channel_name->str();
+  const flatbuffers::String *channel_type = channel->type();
+  CHECK(channel_type != nullptr);
+  type = channel_type->str();
+}
 
 std::string SimpleChannel::DebugString() const {
   return absl::StrCat("{ ", name, ", ", type, "}");
diff --git a/aos/events/simulated_event_loop.cc b/aos/events/simulated_event_loop.cc
index 3c84cfb..64e64ca 100644
--- a/aos/events/simulated_event_loop.cc
+++ b/aos/events/simulated_event_loop.cc
@@ -586,7 +586,7 @@
       const Configuration *configuration,
       std::vector<SimulatedEventLoop *> *event_loops_, const Node *node,
       pid_t tid, EventLoopOptions options)
-      : EventLoop(CHECK_NOTNULL(configuration)),
+      : EventLoop(configuration),
         scheduler_(scheduler),
         node_event_loop_factory_(node_event_loop_factory),
         channels_(channels),
@@ -945,7 +945,8 @@
   if (token_ != scheduler_->InvalidToken()) {
     scheduler_->Deschedule(token_);
   }
-  CHECK_NOTNULL(simulated_channel_)->RemoveWatcher(this);
+  CHECK(simulated_channel_ != nullptr);
+  simulated_channel_->RemoveWatcher(this);
 }
 
 bool SimulatedWatcher::has_run() const {
@@ -1387,8 +1388,13 @@
 
 SimulatedEventLoopFactory::SimulatedEventLoopFactory(
     const Configuration *configuration)
-    : configuration_(CHECK_NOTNULL(configuration)),
-      nodes_(configuration::GetNodes(configuration_)) {
+    : configuration_(configuration),
+      nodes_(
+          // Don't crash if configuration is nullptr, handle it a bit better
+          // before doing anything.
+          configuration == nullptr ? std::vector<const Node *>{}
+                                   : configuration::GetNodes(configuration_)) {
+  CHECK(configuration_ != nullptr);
   CHECK(IsInitialized()) << ": Need to initialize AOS first.";
   for (const Node *node : nodes_) {
     node_factories_.emplace_back(
diff --git a/aos/events/simulated_network_bridge.cc b/aos/events/simulated_network_bridge.cc
index 66c902f..fd2dead 100644
--- a/aos/events/simulated_network_bridge.cc
+++ b/aos/events/simulated_network_bridge.cc
@@ -863,8 +863,11 @@
         }
 
         // And the timestamps are then logged back by us again.
-        if (!delivery_time_is_logged ||
-            CHECK_NOTNULL(delayer)->forwarding_disabled()) {
+        if (!delivery_time_is_logged) {
+          continue;
+        }
+        CHECK(delayer != nullptr);
+        if (delayer->forwarding_disabled()) {
           continue;
         }
 
diff --git a/aos/events/timing_report_dump_lib.cc b/aos/events/timing_report_dump_lib.cc
index 15a8eb9..d83cf69 100644
--- a/aos/events/timing_report_dump_lib.cc
+++ b/aos/events/timing_report_dump_lib.cc
@@ -120,8 +120,9 @@
     std::stringstream errors;
     CHECK(sender->has_error_counts());
     for (size_t ii = 0; ii < sender->error_counts()->size(); ++ii) {
-      const size_t error_count =
-          CHECK_NOTNULL(sender->error_counts()->Get(ii))->count();
+      auto *error_counts = sender->error_counts()->Get(ii);
+      CHECK(error_counts != nullptr);
+      const size_t error_count = error_counts->count();
       errors << error_count;
       if (error_count > 0) {
         // Put send errors onto stderr so that people just interested in
diff --git a/aos/flatbuffer_utils.cc b/aos/flatbuffer_utils.cc
index 5abe676..afa1cb4 100644
--- a/aos/flatbuffer_utils.cc
+++ b/aos/flatbuffer_utils.cc
@@ -6,6 +6,33 @@
 
 namespace aos {
 
+FlatbufferType::FlatbufferType(const flatbuffers::TypeTable *type_table) {
+  CHECK(type_table != nullptr);
+  type_table_ = type_table;
+}
+FlatbufferType::FlatbufferType(const reflection::Schema *schema) {
+  CHECK(schema != nullptr);
+  schema_ = schema;
+  DCHECK(schema->root_table() != nullptr);
+  object_ = schema->root_table();
+}
+
+FlatbufferType::FlatbufferType(const reflection::Schema *schema,
+                               const reflection::Object *object) {
+  CHECK(schema != nullptr);
+  schema_ = schema;
+  DCHECK(object != nullptr);
+  object_ = object;
+}
+
+FlatbufferType::FlatbufferType(const reflection::Schema *schema,
+                               const reflection::Enum *fb_enum) {
+  CHECK(schema != nullptr);
+  schema_ = schema;
+  CHECK(fb_enum != nullptr);
+  enum_ = fb_enum;
+}
+
 bool FlatbufferType::IsSequence() const {
   if (type_table_) {
     return type_table_->st != flatbuffers::ST_ENUM;
diff --git a/aos/flatbuffer_utils.h b/aos/flatbuffer_utils.h
index aa22e68..003f141 100644
--- a/aos/flatbuffer_utils.h
+++ b/aos/flatbuffer_utils.h
@@ -24,11 +24,8 @@
 class FlatbufferType final {
  public:
   // Implicit on purpose, to allow freely creating a FlatbufferType.
-  FlatbufferType(const flatbuffers::TypeTable *type_table)
-      : type_table_(CHECK_NOTNULL(type_table)) {}
-  FlatbufferType(const reflection::Schema *schema)
-      : schema_(CHECK_NOTNULL(schema)),
-        object_(DCHECK_NOTNULL(schema->root_table())) {}
+  FlatbufferType(const flatbuffers::TypeTable *type_table);
+  FlatbufferType(const reflection::Schema *schema);
 
   // This is deliberately copyable, for ease of memory management. It is cheap
   // to pass by value.
@@ -114,11 +111,9 @@
 
  private:
   explicit FlatbufferType(const reflection::Schema *schema,
-                          const reflection::Object *object)
-      : schema_(DCHECK_NOTNULL(schema)), object_(DCHECK_NOTNULL(object)) {}
+                          const reflection::Object *object);
   explicit FlatbufferType(const reflection::Schema *schema,
-                          const reflection::Enum *fb_enum)
-      : schema_(DCHECK_NOTNULL(schema)), enum_(DCHECK_NOTNULL(fb_enum)) {}
+                          const reflection::Enum *fb_enum);
 
   const reflection::Type *ReflectionType(int index) const;
   const reflection::Field *ReflectionObjectField(int index) const;
diff --git a/aos/flatbuffers.h b/aos/flatbuffers.h
index e5de120..f1ed626 100644
--- a/aos/flatbuffers.h
+++ b/aos/flatbuffers.h
@@ -87,10 +87,12 @@
   }
 
   uint8_t *data() final {
-    return reinterpret_cast<uint8_t *>(CHECK_NOTNULL(data_));
+    CHECK(data_ != nullptr);
+    return reinterpret_cast<uint8_t *>(data_);
   }
   const uint8_t *data() const final {
-    return reinterpret_cast<const uint8_t *>(CHECK_NOTNULL(data_));
+    CHECK(data_ != nullptr);
+    return reinterpret_cast<const uint8_t *>(data_);
   }
   size_t size() const final { return size_; }
 
diff --git a/aos/flatbuffers/base.cc b/aos/flatbuffers/base.cc
index afd48a2..f0e7a8b 100644
--- a/aos/flatbuffers/base.cc
+++ b/aos/flatbuffers/base.cc
@@ -51,10 +51,9 @@
   if (parent_ != nullptr) {
     return parent_->InsertBytes(insertion_point, aligned_bytes, set_zero);
   } else {
-    std::optional<std::span<uint8_t>> new_buffer =
-        CHECK_NOTNULL(allocator_)
-            ->InsertBytes(insertion_point, aligned_bytes, Alignment(),
-                          set_zero);
+    CHECK(allocator_ != nullptr);
+    std::optional<std::span<uint8_t>> new_buffer = allocator_->InsertBytes(
+        insertion_point, aligned_bytes, Alignment(), set_zero);
     if (!new_buffer.has_value()) {
       return std::nullopt;
     }
@@ -94,6 +93,7 @@
     if (absolute_offset >= modification_point &&
         object.inline_entry < modification_point) {
       if (*object.inline_entry != 0) {
+        CHECK(object.object != nullptr);
         CHECK_EQ(static_cast<const void *>(
                      static_cast<const uint8_t *>(absolute_offset)),
                  DereferenceOffset(object.inline_entry));
diff --git a/aos/flatbuffers/static_flatbuffers.cc b/aos/flatbuffers/static_flatbuffers.cc
index 4c013a2..449bcbc 100644
--- a/aos/flatbuffers/static_flatbuffers.cc
+++ b/aos/flatbuffers/static_flatbuffers.cc
@@ -558,25 +558,35 @@
       // Unconditionally copy strings/vectors, even if it will just end up
       // being 0-length (this maintains consistency with the flatbuffer Pack()
       // behavior).
-      if (!CHECK_NOTNULL(add_%s())->FromFlatbuffer(other.%s)) {
-        // Fail if we were unable to copy (e.g., if we tried to copy in a long
-        // vector and do not have the space for it).
-        return false;
-      }
-      )code",
-                                           field.name, field.name));
-    } else {
-      // Tables are stored as unique_ptr<FooTable>
-      copiers.emplace_back(absl::StrFormat(R"code(
-      if (other.%s) {
-        if (!CHECK_NOTNULL(add_%s())->FromFlatbuffer(*other.%s)) {
+      {
+        %s* added_%s = add_%s();
+        CHECK(added_%s != nullptr);
+        if (!added_%s->FromFlatbuffer(other.%s)) {
           // Fail if we were unable to copy (e.g., if we tried to copy in a long
           // vector and do not have the space for it).
           return false;
         }
       }
       )code",
-                                           field.name, field.name, field.name));
+                                           field.full_type, field.name,
+                                           field.name, field.name, field.name,
+                                           field.name));
+    } else {
+      // Tables are stored as unique_ptr<FooTable>
+      copiers.emplace_back(absl::StrFormat(R"code(
+      if (other.%s) {
+        %s* added_%s = add_%s();
+        CHECK(added_%s != nullptr);
+        if (!added_%s->FromFlatbuffer(*other.%s)) {
+          // Fail if we were unable to copy (e.g., if we tried to copy in a long
+          // vector and do not have the space for it).
+          return false;
+        }
+      }
+      )code",
+                                           field.name, field.full_type,
+                                           field.name, field.name, field.name,
+                                           field.name, field.name));
     }
   }
   return absl::StrFormat(
@@ -622,14 +632,18 @@
     } else {
       copiers.emplace_back(absl::StrFormat(R"code(
       if (other.has_%s()) {
-        if (!CHECK_NOTNULL(add_%s())->FromFlatbuffer(other.%s())) {
+        %s* added_%s = add_%s();
+        CHECK(added_%s != nullptr);
+        if (!added_%s->FromFlatbuffer(other.%s())) {
           // Fail if we were unable to copy (e.g., if we tried to copy in a long
           // vector and do not have the space for it).
           return false;
         }
       }
       )code",
-                                           field.name, field.name, field.name));
+                                           field.name, field.full_type,
+                                           field.name, field.name, field.name,
+                                           field.name, field.name));
     }
   }
   return absl::StrFormat(
@@ -646,7 +660,8 @@
   // Equivalent to FromFlatbuffer(const Flatbuffer&); this overload is provided
   // to ease implementation of the aos::fbs::Vector internals.
   [[nodiscard]] bool FromFlatbuffer(const Flatbuffer *other) {
-    return FromFlatbuffer(*CHECK_NOTNULL(other));
+    CHECK(other != nullptr);
+    return FromFlatbuffer(*other);
   }
 )code",
       absl::StrJoin(copiers, "\n"));
diff --git a/aos/flatbuffers/static_flatbuffers_test.cc b/aos/flatbuffers/static_flatbuffers_test.cc
index 4a8b9e9..187c72a 100644
--- a/aos/flatbuffers/static_flatbuffers_test.cc
+++ b/aos/flatbuffers/static_flatbuffers_test.cc
@@ -123,7 +123,8 @@
   }
   {
     auto vector_of_strings = object->add_vector_of_strings();
-    auto sub_string = CHECK_NOTNULL(vector_of_strings->emplace_back());
+    auto sub_string = vector_of_strings->emplace_back();
+    CHECK(sub_string != nullptr);
     CHECK(sub_string->emplace_back('D'));
   }
   { object->set_substruct({971, 254}); }
@@ -163,8 +164,13 @@
   builder.add_foo(1234);
   return builder.Finish();
 }
-void PopulateStatic(SubTableStatic *subtable) { subtable->set_foo(1234); }
+void PopulateStatic(SubTableStatic *subtable) {
+  CHECK(subtable != nullptr);
+  subtable->set_foo(1234);
+}
+
 }  // namespace
+
 TEST_F(StaticFlatbuffersTest, PopulateMethodConversionExample) {
   // Using a FlatBufferBuilder:
   flatbuffers::FlatBufferBuilder fbb;
@@ -178,7 +184,7 @@
   // Using the static flatbuffer API.
   aos::fbs::AlignedVectorAllocator allocator;
   Builder<TestTableStatic> static_builder(&allocator);
-  PopulateStatic(CHECK_NOTNULL(static_builder.get()->add_subtable()));
+  PopulateStatic(static_builder.get()->add_subtable());
 
   // And confirm that they both contain the expected flatbuffer:
   const std::string expected = R"json({ "subtable": { "foo": 1234 } })json";
@@ -292,7 +298,8 @@
       EXPECT_FALSE(object->has_vector_of_strings());
       auto vector_of_strings = object->add_vector_of_strings();
       EXPECT_TRUE(object->has_vector_of_strings());
-      auto sub_string = CHECK_NOTNULL(vector_of_strings->emplace_back());
+      auto sub_string = vector_of_strings->emplace_back();
+      CHECK(sub_string != nullptr);
       ASSERT_TRUE(sub_string->emplace_back('D'));
       EXPECT_TRUE(fbs.has_vector_of_strings());
       ASSERT_EQ(1u, fbs.vector_of_strings()->size());
@@ -729,7 +736,8 @@
     ASSERT_TRUE(builder.Verify());
     ASSERT_FALSE(object->has_vector_of_scalars())
         << aos::FlatbufferToJson(builder.AsFlatbufferSpan());
-    vector = CHECK_NOTNULL(object->add_vector_of_scalars());
+    vector = object->add_vector_of_scalars();
+    ASSERT_TRUE(vector != nullptr);
     ASSERT_TRUE(builder.Verify());
     EXPECT_EQ(0u, object->AsFlatbuffer().vector_of_scalars()->size());
     ASSERT_TRUE(vector->emplace_back(9));
@@ -783,7 +791,8 @@
     object->clear_subtable();
     ASSERT_TRUE(builder.Verify());
     EXPECT_FALSE(object->has_subtable());
-    auto subtable = CHECK_NOTNULL(object->add_subtable());
+    auto subtable = object->add_subtable();
+    ASSERT_TRUE(subtable != nullptr);
     subtable->set_baz(9.71);
     EXPECT_EQ(
         R"json({
@@ -806,7 +815,8 @@
     object->clear_subtable();
     ASSERT_TRUE(builder.Verify());
     EXPECT_FALSE(object->has_subtable());
-    subtable = CHECK_NOTNULL(object->add_subtable());
+    subtable = object->add_subtable();
+    ASSERT_TRUE(subtable != nullptr);
     subtable->set_baz(16.78);
     EXPECT_EQ(
         R"json({
@@ -883,7 +893,8 @@
   }
   {
     auto vector_of_strings = object->add_vector_of_strings();
-    auto sub_string = CHECK_NOTNULL(vector_of_strings->emplace_back());
+    auto sub_string = vector_of_strings->emplace_back();
+    ASSERT_TRUE(sub_string != nullptr);
     ASSERT_TRUE(sub_string->emplace_back('D'));
   }
   { object->set_substruct({971, 254}); }
@@ -1048,7 +1059,8 @@
   }
   {
     auto vector_of_strings = object->add_vector_of_strings();
-    auto sub_string = CHECK_NOTNULL(vector_of_strings->emplace_back());
+    auto sub_string = vector_of_strings->emplace_back();
+    ASSERT_TRUE(sub_string != nullptr);
     ASSERT_TRUE(sub_string->emplace_back('D'));
   }
   { object->set_substruct({971, 254}); }
@@ -1153,7 +1165,8 @@
   }
   {
     auto vector_of_strings = object->add_vector_of_strings();
-    auto sub_string = CHECK_NOTNULL(vector_of_strings->emplace_back());
+    auto sub_string = vector_of_strings->emplace_back();
+    ASSERT_TRUE(sub_string != nullptr);
     ASSERT_TRUE(sub_string->emplace_back('D'));
   }
   { object->set_substruct({971, 254}); }
diff --git a/aos/flatbuffers/static_vector.h b/aos/flatbuffers/static_vector.h
index da250e2..f0c48cd 100644
--- a/aos/flatbuffers/static_vector.h
+++ b/aos/flatbuffers/static_vector.h
@@ -409,7 +409,8 @@
   // This is a deep copy, and will call FromFlatbuffer on any constituent
   // objects.
   [[nodiscard]] bool FromFlatbuffer(ConstFlatbuffer *vector) {
-    return FromFlatbuffer(*CHECK_NOTNULL(vector));
+    CHECK(vector != nullptr);
+    return FromFlatbuffer(*vector);
   }
   [[nodiscard]] bool FromFlatbuffer(ConstFlatbuffer &vector);
   // The remaining FromFlatbuffer() overloads are for when using the flatbuffer
@@ -449,8 +450,8 @@
     resize_inline(input_size, SetZero::kNo);
 
     if (input_size > 0) {
-      memcpy(inline_data(), CHECK_NOTNULL(input_data),
-             size() * sizeof(InlineType));
+      CHECK(input_data != nullptr);
+      memcpy(inline_data(), input_data, size() * sizeof(InlineType));
     }
     return true;
   }
@@ -584,7 +585,7 @@
       return;
     } else {
       while (length_ < size) {
-        CHECK_NOTNULL(emplace_back());
+        CHECK(emplace_back() != nullptr);
       }
     }
   }
@@ -725,7 +726,9 @@
     resize_not_inline(0);
 
     for (const auto &entry : vector) {
-      if (!CHECK_NOTNULL(emplace_back())->FromFlatbuffer(entry)) {
+      T *emplaced_entry = emplace_back();
+      CHECK(emplaced_entry != nullptr);
+      if (!emplaced_entry->FromFlatbuffer(entry)) {
         return false;
       }
     }
diff --git a/aos/flatbuffers/test_dir/sample_test_static.h b/aos/flatbuffers/test_dir/sample_test_static.h
index de88c92..1aaf3f6 100644
--- a/aos/flatbuffers/test_dir/sample_test_static.h
+++ b/aos/flatbuffers/test_dir/sample_test_static.h
@@ -137,7 +137,8 @@
   // Equivalent to FromFlatbuffer(const Flatbuffer&); this overload is provided
   // to ease implementation of the aos::fbs::Vector internals.
   [[nodiscard]] bool FromFlatbuffer(const Flatbuffer *other) {
-    return FromFlatbuffer(*CHECK_NOTNULL(other));
+    CHECK(other != nullptr);
+    return FromFlatbuffer(*other);
   }
 
   // Copies the contents of the provided flatbuffer into this flatbuffer,
@@ -348,7 +349,8 @@
   // Equivalent to FromFlatbuffer(const Flatbuffer&); this overload is provided
   // to ease implementation of the aos::fbs::Vector internals.
   [[nodiscard]] bool FromFlatbuffer(const Flatbuffer *other) {
-    return FromFlatbuffer(*CHECK_NOTNULL(other));
+    CHECK(other != nullptr);
+    return FromFlatbuffer(*other);
   }
 
   // Copies the contents of the provided flatbuffer into this flatbuffer,
@@ -1460,8 +1462,10 @@
     }
 
     if (other.has_vector_of_structs()) {
-      if (!CHECK_NOTNULL(add_vector_of_structs())
-               ->FromFlatbuffer(other.vector_of_structs())) {
+      ::aos::fbs::Vector<aos::fbs::testing::SubStruct, 3, true, 0>
+          *added_vector_of_structs = add_vector_of_structs();
+      CHECK(added_vector_of_structs != nullptr);
+      if (!added_vector_of_structs->FromFlatbuffer(other.vector_of_structs())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1469,8 +1473,12 @@
     }
 
     if (other.has_unspecified_length_vector_of_strings()) {
-      if (!CHECK_NOTNULL(add_unspecified_length_vector_of_strings())
-               ->FromFlatbuffer(other.unspecified_length_vector_of_strings())) {
+      ::aos::fbs::Vector<::aos::fbs::String<0>, 0, false, 0>
+          *added_unspecified_length_vector_of_strings =
+              add_unspecified_length_vector_of_strings();
+      CHECK(added_unspecified_length_vector_of_strings != nullptr);
+      if (!added_unspecified_length_vector_of_strings->FromFlatbuffer(
+              other.unspecified_length_vector_of_strings())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1478,8 +1486,10 @@
     }
 
     if (other.has_vector_of_tables()) {
-      if (!CHECK_NOTNULL(add_vector_of_tables())
-               ->FromFlatbuffer(other.vector_of_tables())) {
+      ::aos::fbs::Vector<aos::fbs::testing::SubTableStatic, 3, false, 0>
+          *added_vector_of_tables = add_vector_of_tables();
+      CHECK(added_vector_of_tables != nullptr);
+      if (!added_vector_of_tables->FromFlatbuffer(other.vector_of_tables())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1487,8 +1497,10 @@
     }
 
     if (other.has_vector_aligned()) {
-      if (!CHECK_NOTNULL(add_vector_aligned())
-               ->FromFlatbuffer(other.vector_aligned())) {
+      ::aos::fbs::Vector<int32_t, 3, true, 64> *added_vector_aligned =
+          add_vector_aligned();
+      CHECK(added_vector_aligned != nullptr);
+      if (!added_vector_aligned->FromFlatbuffer(other.vector_aligned())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1496,8 +1508,10 @@
     }
 
     if (other.has_vector_of_strings()) {
-      if (!CHECK_NOTNULL(add_vector_of_strings())
-               ->FromFlatbuffer(other.vector_of_strings())) {
+      ::aos::fbs::Vector<::aos::fbs::String<10>, 3, false, 0>
+          *added_vector_of_strings = add_vector_of_strings();
+      CHECK(added_vector_of_strings != nullptr);
+      if (!added_vector_of_strings->FromFlatbuffer(other.vector_of_strings())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1505,8 +1519,10 @@
     }
 
     if (other.has_vector_of_scalars()) {
-      if (!CHECK_NOTNULL(add_vector_of_scalars())
-               ->FromFlatbuffer(other.vector_of_scalars())) {
+      ::aos::fbs::Vector<int32_t, 3, true, 0> *added_vector_of_scalars =
+          add_vector_of_scalars();
+      CHECK(added_vector_of_scalars != nullptr);
+      if (!added_vector_of_scalars->FromFlatbuffer(other.vector_of_scalars())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1514,8 +1530,11 @@
     }
 
     if (other.has_unspecified_length_string()) {
-      if (!CHECK_NOTNULL(add_unspecified_length_string())
-               ->FromFlatbuffer(other.unspecified_length_string())) {
+      ::aos::fbs::String<0> *added_unspecified_length_string =
+          add_unspecified_length_string();
+      CHECK(added_unspecified_length_string != nullptr);
+      if (!added_unspecified_length_string->FromFlatbuffer(
+              other.unspecified_length_string())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1523,8 +1542,11 @@
     }
 
     if (other.has_unspecified_length_vector()) {
-      if (!CHECK_NOTNULL(add_unspecified_length_vector())
-               ->FromFlatbuffer(other.unspecified_length_vector())) {
+      ::aos::fbs::Vector<uint8_t, 0, true, 0> *added_unspecified_length_vector =
+          add_unspecified_length_vector();
+      CHECK(added_unspecified_length_vector != nullptr);
+      if (!added_unspecified_length_vector->FromFlatbuffer(
+              other.unspecified_length_vector())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1532,8 +1554,10 @@
     }
 
     if (other.has_included_table()) {
-      if (!CHECK_NOTNULL(add_included_table())
-               ->FromFlatbuffer(other.included_table())) {
+      aos::fbs::testing::included::IncludedTableStatic *added_included_table =
+          add_included_table();
+      CHECK(added_included_table != nullptr);
+      if (!added_included_table->FromFlatbuffer(other.included_table())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1541,7 +1565,9 @@
     }
 
     if (other.has_subtable()) {
-      if (!CHECK_NOTNULL(add_subtable())->FromFlatbuffer(other.subtable())) {
+      aos::fbs::testing::SubTableStatic *added_subtable = add_subtable();
+      CHECK(added_subtable != nullptr);
+      if (!added_subtable->FromFlatbuffer(other.subtable())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1549,7 +1575,9 @@
     }
 
     if (other.has_string()) {
-      if (!CHECK_NOTNULL(add_string())->FromFlatbuffer(other.string())) {
+      ::aos::fbs::String<20> *added_string = add_string();
+      CHECK(added_string != nullptr);
+      if (!added_string->FromFlatbuffer(other.string())) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1565,7 +1593,8 @@
   // Equivalent to FromFlatbuffer(const Flatbuffer&); this overload is provided
   // to ease implementation of the aos::fbs::Vector internals.
   [[nodiscard]] bool FromFlatbuffer(const Flatbuffer *other) {
-    return FromFlatbuffer(*CHECK_NOTNULL(other));
+    CHECK(other != nullptr);
+    return FromFlatbuffer(*other);
   }
 
   // Copies the contents of the provided flatbuffer into this flatbuffer,
@@ -1585,86 +1614,124 @@
     // Unconditionally copy strings/vectors, even if it will just end up
     // being 0-length (this maintains consistency with the flatbuffer Pack()
     // behavior).
-    if (!CHECK_NOTNULL(add_vector_of_structs())
-             ->FromFlatbuffer(other.vector_of_structs)) {
-      // Fail if we were unable to copy (e.g., if we tried to copy in a long
-      // vector and do not have the space for it).
-      return false;
+    {
+      ::aos::fbs::Vector<aos::fbs::testing::SubStruct, 3, true, 0>
+          *added_vector_of_structs = add_vector_of_structs();
+      CHECK(added_vector_of_structs != nullptr);
+      if (!added_vector_of_structs->FromFlatbuffer(other.vector_of_structs)) {
+        // Fail if we were unable to copy (e.g., if we tried to copy in a long
+        // vector and do not have the space for it).
+        return false;
+      }
     }
 
     // Unconditionally copy strings/vectors, even if it will just end up
     // being 0-length (this maintains consistency with the flatbuffer Pack()
     // behavior).
-    if (!CHECK_NOTNULL(add_unspecified_length_vector_of_strings())
-             ->FromFlatbuffer(other.unspecified_length_vector_of_strings)) {
-      // Fail if we were unable to copy (e.g., if we tried to copy in a long
-      // vector and do not have the space for it).
-      return false;
+    {
+      ::aos::fbs::Vector<::aos::fbs::String<0>, 0, false, 0>
+          *added_unspecified_length_vector_of_strings =
+              add_unspecified_length_vector_of_strings();
+      CHECK(added_unspecified_length_vector_of_strings != nullptr);
+      if (!added_unspecified_length_vector_of_strings->FromFlatbuffer(
+              other.unspecified_length_vector_of_strings)) {
+        // Fail if we were unable to copy (e.g., if we tried to copy in a long
+        // vector and do not have the space for it).
+        return false;
+      }
     }
 
     // Unconditionally copy strings/vectors, even if it will just end up
     // being 0-length (this maintains consistency with the flatbuffer Pack()
     // behavior).
-    if (!CHECK_NOTNULL(add_vector_of_tables())
-             ->FromFlatbuffer(other.vector_of_tables)) {
-      // Fail if we were unable to copy (e.g., if we tried to copy in a long
-      // vector and do not have the space for it).
-      return false;
+    {
+      ::aos::fbs::Vector<aos::fbs::testing::SubTableStatic, 3, false, 0>
+          *added_vector_of_tables = add_vector_of_tables();
+      CHECK(added_vector_of_tables != nullptr);
+      if (!added_vector_of_tables->FromFlatbuffer(other.vector_of_tables)) {
+        // Fail if we were unable to copy (e.g., if we tried to copy in a long
+        // vector and do not have the space for it).
+        return false;
+      }
     }
 
     // Unconditionally copy strings/vectors, even if it will just end up
     // being 0-length (this maintains consistency with the flatbuffer Pack()
     // behavior).
-    if (!CHECK_NOTNULL(add_vector_aligned())
-             ->FromFlatbuffer(other.vector_aligned)) {
-      // Fail if we were unable to copy (e.g., if we tried to copy in a long
-      // vector and do not have the space for it).
-      return false;
+    {
+      ::aos::fbs::Vector<int32_t, 3, true, 64> *added_vector_aligned =
+          add_vector_aligned();
+      CHECK(added_vector_aligned != nullptr);
+      if (!added_vector_aligned->FromFlatbuffer(other.vector_aligned)) {
+        // Fail if we were unable to copy (e.g., if we tried to copy in a long
+        // vector and do not have the space for it).
+        return false;
+      }
     }
 
     // Unconditionally copy strings/vectors, even if it will just end up
     // being 0-length (this maintains consistency with the flatbuffer Pack()
     // behavior).
-    if (!CHECK_NOTNULL(add_vector_of_strings())
-             ->FromFlatbuffer(other.vector_of_strings)) {
-      // Fail if we were unable to copy (e.g., if we tried to copy in a long
-      // vector and do not have the space for it).
-      return false;
+    {
+      ::aos::fbs::Vector<::aos::fbs::String<10>, 3, false, 0>
+          *added_vector_of_strings = add_vector_of_strings();
+      CHECK(added_vector_of_strings != nullptr);
+      if (!added_vector_of_strings->FromFlatbuffer(other.vector_of_strings)) {
+        // Fail if we were unable to copy (e.g., if we tried to copy in a long
+        // vector and do not have the space for it).
+        return false;
+      }
     }
 
     // Unconditionally copy strings/vectors, even if it will just end up
     // being 0-length (this maintains consistency with the flatbuffer Pack()
     // behavior).
-    if (!CHECK_NOTNULL(add_vector_of_scalars())
-             ->FromFlatbuffer(other.vector_of_scalars)) {
-      // Fail if we were unable to copy (e.g., if we tried to copy in a long
-      // vector and do not have the space for it).
-      return false;
+    {
+      ::aos::fbs::Vector<int32_t, 3, true, 0> *added_vector_of_scalars =
+          add_vector_of_scalars();
+      CHECK(added_vector_of_scalars != nullptr);
+      if (!added_vector_of_scalars->FromFlatbuffer(other.vector_of_scalars)) {
+        // Fail if we were unable to copy (e.g., if we tried to copy in a long
+        // vector and do not have the space for it).
+        return false;
+      }
     }
 
     // Unconditionally copy strings/vectors, even if it will just end up
     // being 0-length (this maintains consistency with the flatbuffer Pack()
     // behavior).
-    if (!CHECK_NOTNULL(add_unspecified_length_string())
-             ->FromFlatbuffer(other.unspecified_length_string)) {
-      // Fail if we were unable to copy (e.g., if we tried to copy in a long
-      // vector and do not have the space for it).
-      return false;
+    {
+      ::aos::fbs::String<0> *added_unspecified_length_string =
+          add_unspecified_length_string();
+      CHECK(added_unspecified_length_string != nullptr);
+      if (!added_unspecified_length_string->FromFlatbuffer(
+              other.unspecified_length_string)) {
+        // Fail if we were unable to copy (e.g., if we tried to copy in a long
+        // vector and do not have the space for it).
+        return false;
+      }
     }
 
     // Unconditionally copy strings/vectors, even if it will just end up
     // being 0-length (this maintains consistency with the flatbuffer Pack()
     // behavior).
-    if (!CHECK_NOTNULL(add_unspecified_length_vector())
-             ->FromFlatbuffer(other.unspecified_length_vector)) {
-      // Fail if we were unable to copy (e.g., if we tried to copy in a long
-      // vector and do not have the space for it).
-      return false;
+    {
+      ::aos::fbs::Vector<uint8_t, 0, true, 0> *added_unspecified_length_vector =
+          add_unspecified_length_vector();
+      CHECK(added_unspecified_length_vector != nullptr);
+      if (!added_unspecified_length_vector->FromFlatbuffer(
+              other.unspecified_length_vector)) {
+        // Fail if we were unable to copy (e.g., if we tried to copy in a long
+        // vector and do not have the space for it).
+        return false;
+      }
     }
 
     if (other.included_table) {
-      if (!CHECK_NOTNULL(add_included_table())
-               ->FromFlatbuffer(*other.included_table)) {
+      aos::fbs::testing::included::IncludedTableStatic *added_included_table =
+          add_included_table();
+      CHECK(added_included_table != nullptr);
+      if (!added_included_table->FromFlatbuffer(*other.included_table)) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1672,7 +1739,9 @@
     }
 
     if (other.subtable) {
-      if (!CHECK_NOTNULL(add_subtable())->FromFlatbuffer(*other.subtable)) {
+      aos::fbs::testing::SubTableStatic *added_subtable = add_subtable();
+      CHECK(added_subtable != nullptr);
+      if (!added_subtable->FromFlatbuffer(*other.subtable)) {
         // Fail if we were unable to copy (e.g., if we tried to copy in a long
         // vector and do not have the space for it).
         return false;
@@ -1682,10 +1751,14 @@
     // Unconditionally copy strings/vectors, even if it will just end up
     // being 0-length (this maintains consistency with the flatbuffer Pack()
     // behavior).
-    if (!CHECK_NOTNULL(add_string())->FromFlatbuffer(other.string)) {
-      // Fail if we were unable to copy (e.g., if we tried to copy in a long
-      // vector and do not have the space for it).
-      return false;
+    {
+      ::aos::fbs::String<20> *added_string = add_string();
+      CHECK(added_string != nullptr);
+      if (!added_string->FromFlatbuffer(other.string)) {
+        // Fail if we were unable to copy (e.g., if we tried to copy in a long
+        // vector and do not have the space for it).
+        return false;
+      }
     }
 
     set_scalar(other.scalar);
diff --git a/aos/ipc_lib/memory_estimation.cc b/aos/ipc_lib/memory_estimation.cc
index d193c75..b64cb3a 100644
--- a/aos/ipc_lib/memory_estimation.cc
+++ b/aos/ipc_lib/memory_estimation.cc
@@ -5,7 +5,10 @@
 size_t TotalSharedMemoryUsage(const aos::Configuration *config,
                               const aos::Node *node) {
   size_t total_size = 0;
-  for (const aos::Channel *channel : *CHECK_NOTNULL(config->channels())) {
+  const flatbuffers::Vector<flatbuffers::Offset<aos::Channel>> *channels =
+      config->channels();
+  CHECK(channels != nullptr);
+  for (const aos::Channel *channel : *channels) {
     if (aos::configuration::ChannelIsReadableOnNode(channel, node)) {
       total_size +=
           LocklessQueueMemorySize(MakeQueueConfiguration(config, channel));
diff --git a/aos/network/message_bridge_client_lib.cc b/aos/network/message_bridge_client_lib.cc
index 90c0cc0..cf52a69 100644
--- a/aos/network/message_bridge_client_lib.cc
+++ b/aos/network/message_bridge_client_lib.cc
@@ -117,8 +117,12 @@
                                           remote_name, event_loop->boot_uuid(),
                                           config_sha256)),
       message_reception_reply_(MakeMessageHeaderReply()),
-      remote_node_(CHECK_NOTNULL(
-          configuration::GetNode(event_loop->configuration(), remote_name))),
+      remote_node_([&]() {
+        const aos::Node *node =
+            configuration::GetNode(event_loop->configuration(), remote_name);
+        CHECK(node != nullptr);
+        return node;
+      }()),
       client_(remote_node_->hostname()->string_view(), remote_node_->port(),
               connect_message_.message().channels_to_transfer()->size() +
                   kControlStreams(),
diff --git a/aos/network/message_bridge_server_lib.cc b/aos/network/message_bridge_server_lib.cc
index 3c7a8d2..a3f429a 100644
--- a/aos/network/message_bridge_server_lib.cc
+++ b/aos/network/message_bridge_server_lib.cc
@@ -809,12 +809,12 @@
     }
 
     CHECK_LT(message_header->channel_index(), channels_.size());
-    CHECK_NOTNULL(channels_[message_header->channel_index()])
-        ->HandleDelivery(
-            message->header.rcvinfo.rcv_assoc_id,
-            message->header.rcvinfo.rcv_ssn,
-            absl::Span<const uint8_t>(message->data(), message->size),
-            message->partial_deliveries, &server_status_);
+    ChannelState *channel = channels_[message_header->channel_index()].get();
+    CHECK(channel != nullptr);
+    channel->HandleDelivery(
+        message->header.rcvinfo.rcv_assoc_id, message->header.rcvinfo.rcv_ssn,
+        absl::Span<const uint8_t>(message->data(), message->size),
+        message->partial_deliveries, &server_status_);
     if (VLOG_IS_ON(2)) {
       message->LogRcvInfo();
     }
diff --git a/aos/network/message_bridge_test.cc b/aos/network/message_bridge_test.cc
index 2dac8ed..350cf26 100644
--- a/aos/network/message_bridge_test.cc
+++ b/aos/network/message_bridge_test.cc
@@ -1368,8 +1368,9 @@
         std::make_unique<aos::ShmEventLoop>(&config_.message());
     pi2_.client_event_loop_->SetRuntimeRealtimePriority(1);
 
-    const aos::Node *const remote_node = CHECK_NOTNULL(configuration::GetNode(
-        pi2_.client_event_loop_->configuration(), "pi1"));
+    const aos::Node *const remote_node =
+        configuration::GetNode(pi2_.client_event_loop_->configuration(), "pi1");
+    CHECK(remote_node != nullptr);
 
     const aos::FlatbufferDetachedBuffer<aos::message_bridge::Connect>
         connect_message(MakeConnectMessage(
diff --git a/aos/network/multinode_timestamp_filter.cc b/aos/network/multinode_timestamp_filter.cc
index 1869ffb..42e4299 100644
--- a/aos/network/multinode_timestamp_filter.cc
+++ b/aos/network/multinode_timestamp_filter.cc
@@ -2017,7 +2017,7 @@
               // Got a forwarding timestamp!
               NoncausalOffsetEstimator *filter =
                   filters_per_channel_[node_index][msg->channel_index];
-              CHECK_NOTNULL(filter);
+              CHECK(filter != nullptr);
               const Node *node = configuration()->nodes()->Get(node_index);
 
               // The remote time could be from a reliable message long ago,
diff --git a/aos/network/rawrtc.cc b/aos/network/rawrtc.cc
index e519b2e..6d9bc3d 100644
--- a/aos/network/rawrtc.cc
+++ b/aos/network/rawrtc.cc
@@ -164,8 +164,8 @@
 
 void ScopedDataChannel::Send(struct mbuf *buffer) {
   // TODO(austin): Checking isn't right, handle errors more gracefully.
-  CHECK_RAWRTC(
-      rawrtc_data_channel_send(CHECK_NOTNULL(data_channel_), buffer, true));
+  CHECK(data_channel_ != nullptr);
+  CHECK_RAWRTC(rawrtc_data_channel_send(data_channel_, buffer, true));
 }
 
 uint64_t ScopedDataChannel::buffered_amount() {
@@ -173,8 +173,8 @@
 
   // TODO(austin): Not implemented yet...
   uint64_t result;
-  CHECK_RAWRTC(rawrtc_data_channel_get_buffered_amount(
-      &result, CHECK_NOTNULL(data_channel_)));
+  CHECK(data_channel_ != nullptr);
+  CHECK_RAWRTC(rawrtc_data_channel_get_buffered_amount(&result, data_channel_));
   return result;
 }
 
diff --git a/aos/network/web_proxy.cc b/aos/network/web_proxy.cc
index 15ebb66..6b71433 100644
--- a/aos/network/web_proxy.cc
+++ b/aos/network/web_proxy.cc
@@ -333,7 +333,7 @@
 
 std::shared_ptr<struct mbuf> Subscriber::NextBuffer(
     ChannelInformation *channel) {
-  CHECK_NOTNULL(channel);
+  CHECK(channel != nullptr);
   if (message_buffer_.empty()) {
     return nullptr;
   }
@@ -400,7 +400,7 @@
 }
 
 void Subscriber::SkipToLastMessage(ChannelInformation *channel) {
-  CHECK_NOTNULL(channel);
+  CHECK(channel != nullptr);
   if (message_buffer_.empty() ||
       channel->current_queue_index == message_buffer_.back().index) {
     return;
diff --git a/aos/starter/starter_rpc_lib.cc b/aos/starter/starter_rpc_lib.cc
index 230e1b1..b497792 100644
--- a/aos/starter/starter_rpc_lib.cc
+++ b/aos/starter/starter_rpc_lib.cc
@@ -155,9 +155,9 @@
       if (is_multi_node) {
         node_offsets.push_back(builder.fbb()->CreateString(node_name));
       }
-      const ApplicationStatus *last_status =
-          CHECK_NOTNULL(FindApplicationStatus(*status_fetchers_[node_name],
-                                              command.application));
+      const ApplicationStatus *last_status = FindApplicationStatus(
+          *status_fetchers_[node_name], command.application);
+      CHECK(last_status != nullptr);
       current_commands_[node_name].push_back(CommandStatus{
           .expected_state = ExpectedStateForCommand(command.command),
           .application = std::string(command.application),
@@ -207,7 +207,8 @@
     const Status &status = *status_fetchers_[pair.first];
     for (const auto &command : pair.second) {
       const ApplicationStatus *application_status =
-          CHECK_NOTNULL(FindApplicationStatus(status, command.application));
+          FindApplicationStatus(status, command.application);
+      CHECK(application_status != nullptr);
       if (application_status->state() == command.expected_state) {
         if (command.expected_state == State::RUNNING &&
             application_status->id() == command.old_id) {
diff --git a/aos/starter/starterd_lib.cc b/aos/starter/starterd_lib.cc
index 6917bb5..79e564e 100644
--- a/aos/starter/starterd_lib.cc
+++ b/aos/starter/starterd_lib.cc
@@ -321,7 +321,7 @@
 }
 
 void Starter::AddChannel(const aos::Channel *channel) {
-  CHECK_NOTNULL(channel);
+  CHECK(channel != nullptr);
   std::unique_ptr<aos::ipc_lib::MemoryMappedQueue> queue =
       std::make_unique<aos::ipc_lib::MemoryMappedQueue>(
           shm_base_, FLAGS_permissions, event_loop_.configuration(), channel);
diff --git a/aos/starter/subprocess.cc b/aos/starter/subprocess.cc
index 60f6b92..c36d59b 100644
--- a/aos/starter/subprocess.cc
+++ b/aos/starter/subprocess.cc
@@ -637,7 +637,7 @@
                             util::Top *top) {
   UpdateFileState();
 
-  CHECK_NOTNULL(builder);
+  CHECK(builder != nullptr);
   auto name_fbs = builder->CreateString(name_);
 
   const bool valid_pid = pid_ > 0 && status_ != aos::starter::State::STOPPED;
diff --git a/aos/util/config_validator_lib.cc b/aos/util/config_validator_lib.cc
index eb5205a..4347017 100644
--- a/aos/util/config_validator_lib.cc
+++ b/aos/util/config_validator_lib.cc
@@ -177,8 +177,10 @@
               }
               // TODO(james): This will be overly noisy, as it ends up
               // CHECK-failing.
-              required_timestamp_channels.insert(CHECK_NOTNULL(
-                  timestamp_finder.ForChannel(channel, connection)));
+              const Channel *found_channel =
+                  timestamp_finder.ForChannel(channel, connection);
+              CHECK(found_channel != nullptr);
+              required_timestamp_channels.insert(found_channel);
               break;
           }
         }
diff --git a/aos/util/error_counter.h b/aos/util/error_counter.h
index e08c67e..7837f9e 100644
--- a/aos/util/error_counter.h
+++ b/aos/util/error_counter.h
@@ -51,7 +51,8 @@
   static void InitializeStaticFbs(Static *builder) {
     CHECK(builder->reserve(kNumErrors));
     for (size_t ii = 0; ii < kNumErrors; ++ii) {
-      auto element = CHECK_NOTNULL(builder->emplace_back());
+      auto element = builder->emplace_back();
+      CHECK(element != nullptr);
       element->set_error(static_cast<Error>(ii));
       element->set_count(0);
     }
@@ -65,7 +66,7 @@
   void InvalidateBuffer() { vector_ = nullptr; }
 
   void IncrementError(Error error) {
-    CHECK_NOTNULL(vector_);
+    CHECK(vector_ != nullptr);
     DCHECK_LT(static_cast<size_t>(error), vector_->size());
     Count *counter = vector_->GetMutableObject(static_cast<size_t>(error));
     counter->mutate_count(counter->count() + 1);
@@ -73,7 +74,7 @@
 
   // Sets all the error counts to zero.
   void ResetCounts() {
-    CHECK_NOTNULL(vector_);
+    CHECK(vector_ != nullptr);
     DCHECK_EQ(vector_->size(), kNumErrors) << this << " vector " << vector_;
     for (size_t ii = 0; ii < kNumErrors; ++ii) {
       vector_->GetMutableObject(ii)->mutate_count(0);
diff --git a/aos/util/mcap_logger.cc b/aos/util/mcap_logger.cc
index 0dbb88e..a70da62 100644
--- a/aos/util/mcap_logger.cc
+++ b/aos/util/mcap_logger.cc
@@ -422,7 +422,7 @@
   if (!wrote_configuration_) {
     WriteConfigurationMessage();
   }
-  CHECK_NOTNULL(context.data);
+  CHECK(context.data != nullptr);
 
   message_counts_[channel_id]++;
 
diff --git a/aos/util/scoped_pipe.cc b/aos/util/scoped_pipe.cc
index a4e5b46..d178c0d 100644
--- a/aos/util/scoped_pipe.cc
+++ b/aos/util/scoped_pipe.cc
@@ -49,7 +49,7 @@
 }
 
 size_t ScopedPipe::ScopedReadPipe::Read(std::string *buffer) {
-  CHECK_NOTNULL(buffer);
+  CHECK(buffer != nullptr);
   constexpr ssize_t kBufferSize = 1024;
   const size_t original_size = buffer->size();
   size_t read_bytes = 0;
diff --git a/frc971/constants/constants_sender_lib.h b/frc971/constants/constants_sender_lib.h
index 9bd2c00..203435a 100644
--- a/frc971/constants/constants_sender_lib.h
+++ b/frc971/constants/constants_sender_lib.h
@@ -82,7 +82,10 @@
     });
   }
 
-  const ConstantsData &constants() const { return *fetcher_.get(); }
+  const ConstantsData &constants() const {
+    CHECK(fetcher_.get() != nullptr);
+    return *fetcher_.get();
+  }
 
  private:
   aos::Fetcher<ConstantsData> fetcher_;
diff --git a/frc971/control_loops/catapult/catapult.cc b/frc971/control_loops/catapult/catapult.cc
index a827dc9..153d35c 100644
--- a/frc971/control_loops/catapult/catapult.cc
+++ b/frc971/control_loops/catapult/catapult.cc
@@ -64,7 +64,7 @@
         std::optional<double> solution = catapult_mpc_.Next();
 
         if (!solution.has_value()) {
-          CHECK_NOTNULL(catapult_voltage);
+          CHECK(catapult_voltage != nullptr);
           *catapult_voltage = 0.0;
           if (catapult_mpc_.started()) {
             ++shot_count_;
@@ -73,7 +73,7 @@
           }
         } else {
           // TODO(austin): Voltage error?
-          CHECK_NOTNULL(catapult_voltage);
+          CHECK(catapult_voltage != nullptr);
           if (current_horizon_ == 1) {
             battery_voltage = 12.0;
           }
diff --git a/frc971/control_loops/drivetrain/distance_spline.cc b/frc971/control_loops/drivetrain/distance_spline.cc
index bcd9d4c..80ef4c4 100644
--- a/frc971/control_loops/drivetrain/distance_spline.cc
+++ b/frc971/control_loops/drivetrain/distance_spline.cc
@@ -77,7 +77,7 @@
 }
 
 std::vector<Spline> FlatbufferToSplines(const MultiSpline *fb) {
-  CHECK_NOTNULL(fb);
+  CHECK(fb != nullptr);
   const size_t spline_count = fb->spline_count();
   CHECK_EQ(fb->spline_x()->size(), static_cast<size_t>(spline_count * 5 + 1));
   CHECK_EQ(fb->spline_y()->size(), static_cast<size_t>(spline_count * 5 + 1));
@@ -95,7 +95,7 @@
 
 aos::SizedArray<Spline, FinishedDistanceSpline::kMaxSplines>
 SizedFlatbufferToSplines(const MultiSpline *fb) {
-  CHECK_NOTNULL(fb);
+  CHECK(fb != nullptr);
   const size_t spline_count = fb->spline_count();
   CHECK_EQ(fb->spline_x()->size(), static_cast<size_t>(spline_count * 5 + 1));
   CHECK_EQ(fb->spline_y()->size(), static_cast<size_t>(spline_count * 5 + 1));
@@ -141,8 +141,8 @@
       fbb->CreateUninitializedVector(num_points, &spline_x_vector);
   const flatbuffers::Offset<flatbuffers::Vector<float>> spline_y_offset =
       fbb->CreateUninitializedVector(num_points, &spline_y_vector);
-  CHECK_NOTNULL(spline_x_vector);
-  CHECK_NOTNULL(spline_y_vector);
+  CHECK(spline_x_vector != nullptr);
+  CHECK(spline_y_vector != nullptr);
   spline_x_vector[0] = splines()[0].control_points()(0, 0);
   spline_y_vector[0] = splines()[0].control_points()(1, 0);
   for (size_t spline_index = 0; spline_index < splines().size();
diff --git a/frc971/control_loops/drivetrain/drivetrain_config.h b/frc971/control_loops/drivetrain/drivetrain_config.h
index 4c35b6a..ae1a31a 100644
--- a/frc971/control_loops/drivetrain/drivetrain_config.h
+++ b/frc971/control_loops/drivetrain/drivetrain_config.h
@@ -43,9 +43,11 @@
     if (fbs == nullptr) {
       return {};
     }
+    CHECK(fbs->q() != nullptr);
+    CHECK(fbs->r() != nullptr);
     return LineFollowConfig{
-        .Q = ToEigenOrDie<3, 3>(*CHECK_NOTNULL(fbs->q())),
-        .R = ToEigenOrDie<2, 2>(*CHECK_NOTNULL(fbs->r())),
+        .Q = ToEigenOrDie<3, 3>(*fbs->q()),
+        .R = ToEigenOrDie<2, 2>(*fbs->r()),
         .max_controllable_offset = fbs->max_controllable_offset()};
   }
 };
@@ -71,9 +73,10 @@
     if (fbs == nullptr) {
       return {};
     }
-    return SplineFollowerConfig{
-        .Q = ToEigenOrDie<5, 5>(*CHECK_NOTNULL(fbs->q())),
-        .R = ToEigenOrDie<2, 2>(*CHECK_NOTNULL(fbs->r()))};
+    CHECK(fbs->q() != nullptr);
+    CHECK(fbs->r() != nullptr);
+    return SplineFollowerConfig{.Q = ToEigenOrDie<5, 5>(*fbs->q()),
+                                .R = ToEigenOrDie<2, 2>(*fbs->r())};
   }
 };
 
@@ -205,36 +208,45 @@
         fbs_copy = std::make_shared<
             aos::FlatbufferDetachedBuffer<fbs::DrivetrainConfig>>(
             aos::RecursiveCopyFlatBuffer(&fbs));
+    CHECK(fbs_copy->message().loop_config()->drivetrain_loop() != nullptr);
+    CHECK(fbs_copy->message().loop_config()->velocity_drivetrain_loop() !=
+          nullptr);
+    CHECK(fbs_copy->message().loop_config()->kalman_drivetrain_loop() !=
+          nullptr);
+    CHECK(
+        fbs_copy->message().loop_config()->hybrid_velocity_drivetrain_loop() !=
+        nullptr);
+    CHECK(fbs.imu_transform() != nullptr);
     return {
 #define ASSIGN(field) .field = fbs.field()
       ASSIGN(shifter_type), ASSIGN(loop_type), ASSIGN(gyro_type),
           ASSIGN(imu_type),
           .make_drivetrain_loop =
               [fbs_copy]() {
-                return MakeStateFeedbackLoop<4, 2, 2>(*CHECK_NOTNULL(
-                    fbs_copy->message().loop_config()->drivetrain_loop()));
+                return MakeStateFeedbackLoop<4, 2, 2>(
+                    *fbs_copy->message().loop_config()->drivetrain_loop());
               },
           .make_v_drivetrain_loop =
               [fbs_copy]() {
                 return MakeStateFeedbackLoop<2, 2, 2>(
-                    *CHECK_NOTNULL(fbs_copy->message()
-                                       .loop_config()
-                                       ->velocity_drivetrain_loop()));
+                    *fbs_copy->message()
+                         .loop_config()
+                         ->velocity_drivetrain_loop());
               },
           .make_kf_drivetrain_loop =
               [fbs_copy]() {
                 return MakeStateFeedbackLoop<7, 2, 4>(
-                    *CHECK_NOTNULL(fbs_copy->message()
-                                       .loop_config()
-                                       ->kalman_drivetrain_loop()));
+                    *fbs_copy->message()
+                         .loop_config()
+                         ->kalman_drivetrain_loop());
               },
 #if defined(__linux__)
           .make_hybrid_drivetrain_velocity_loop =
               [fbs_copy]() {
                 return MakeHybridStateFeedbackLoop<2, 2, 2>(
-                    *CHECK_NOTNULL(fbs_copy->message()
-                                       .loop_config()
-                                       ->hybrid_velocity_drivetrain_loop()));
+                    *fbs_copy->message()
+                         .loop_config()
+                         ->hybrid_velocity_drivetrain_loop());
               },
 #endif
           .dt = std::chrono::nanoseconds(fbs.loop_config()->dt()),
@@ -253,8 +265,7 @@
           ASSIGN(wheel_non_linearity), ASSIGN(quickturn_wheel_multiplier),
           ASSIGN(wheel_multiplier),
           ASSIGN(pistol_grip_shift_enables_line_follow),
-          .imu_transform =
-              ToEigenOrDie<3, 3>(*CHECK_NOTNULL(fbs.imu_transform())),
+          .imu_transform = ToEigenOrDie<3, 3>(*fbs.imu_transform()),
           ASSIGN(is_simulated),
           .down_estimator_config =
               aos::UnpackFlatbuffer(fbs.down_estimator_config()),
diff --git a/frc971/control_loops/drivetrain/drivetrain_lib_test.cc b/frc971/control_loops/drivetrain/drivetrain_lib_test.cc
index 5082f39..c1aa2a5 100644
--- a/frc971/control_loops/drivetrain/drivetrain_lib_test.cc
+++ b/frc971/control_loops/drivetrain/drivetrain_lib_test.cc
@@ -75,7 +75,8 @@
     // Run for enough time to allow the gyro/imu zeroing code to run.
     RunFor(std::chrono::seconds(15));
     CHECK(drivetrain_status_fetcher_.Fetch());
-    EXPECT_TRUE(CHECK_NOTNULL(drivetrain_status_fetcher_->zeroing())->zeroed());
+    CHECK(drivetrain_status_fetcher_->zeroing() != nullptr);
+    EXPECT_TRUE(drivetrain_status_fetcher_->zeroing()->zeroed());
   }
   virtual ~DrivetrainTest() {}
 
@@ -97,10 +98,11 @@
 
   void VerifyNearSplineGoal() {
     drivetrain_status_fetcher_.Fetch();
+    CHECK(drivetrain_status_fetcher_->trajectory_logging() != nullptr);
     const double expected_x =
-        CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())->x();
+        drivetrain_status_fetcher_->trajectory_logging()->x();
     const double expected_y =
-        CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())->y();
+        drivetrain_status_fetcher_->trajectory_logging()->y();
     const double estimated_x = drivetrain_status_fetcher_->x();
     const double estimated_y = drivetrain_status_fetcher_->y();
     const ::Eigen::Vector2d actual = drivetrain_plant_.GetPosition();
@@ -114,15 +116,16 @@
     do {
       RunFor(dt());
       EXPECT_TRUE(drivetrain_status_fetcher_.Fetch());
-    } while (!CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())
-                  ->is_executed());
+      CHECK(drivetrain_status_fetcher_->trajectory_logging() != nullptr);
+    } while (!drivetrain_status_fetcher_->trajectory_logging()->is_executed());
   }
 
   void VerifyDownEstimator() {
     EXPECT_TRUE(drivetrain_status_fetcher_.Fetch());
     // TODO(james): Handle Euler angle singularities...
+    CHECK(drivetrain_status_fetcher_->down_estimator() != nullptr);
     const double down_estimator_yaw =
-        CHECK_NOTNULL(drivetrain_status_fetcher_->down_estimator())->yaw();
+        drivetrain_status_fetcher_->down_estimator()->yaw();
     const double localizer_yaw = drivetrain_status_fetcher_->theta();
     EXPECT_LT(std::abs(aos::math::DiffAngle(down_estimator_yaw, localizer_yaw)),
               1e-2);
@@ -636,8 +639,9 @@
   // Check that we are pointed the right direction:
   drivetrain_status_fetcher_.Fetch();
   auto actual = drivetrain_plant_.state();
+  CHECK(drivetrain_status_fetcher_->trajectory_logging() != nullptr);
   const double expected_theta =
-      CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())->theta();
+      drivetrain_status_fetcher_->trajectory_logging()->theta();
   // As a sanity check, compare both against absolute angle and the spline's
   // goal angle.
   EXPECT_NEAR(0.0, ::aos::math::DiffAngle(actual(2), 0.0), 5e-2);
@@ -739,10 +743,9 @@
     EXPECT_EQ(0.0, drivetrain_output_fetcher_->right_voltage());
     // The goal should be null after stopping.
     ASSERT_TRUE(drivetrain_status_fetcher_.Fetch());
-    EXPECT_FALSE(CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())
-                     ->has_x());
-    EXPECT_FALSE(CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())
-                     ->has_y());
+    CHECK(drivetrain_status_fetcher_->trajectory_logging() != nullptr);
+    EXPECT_FALSE(drivetrain_status_fetcher_->trajectory_logging()->has_x());
+    EXPECT_FALSE(drivetrain_status_fetcher_->trajectory_logging()->has_y());
   }
 }
 
@@ -808,10 +811,9 @@
 
   // The goal should be empty.
   drivetrain_status_fetcher_.Fetch();
-  EXPECT_FALSE(
-      CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())->has_x());
-  EXPECT_FALSE(
-      CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())->has_y());
+  CHECK(drivetrain_status_fetcher_->trajectory_logging() != nullptr);
+  EXPECT_FALSE(drivetrain_status_fetcher_->trajectory_logging()->has_x());
+  EXPECT_FALSE(drivetrain_status_fetcher_->trajectory_logging()->has_y());
 }
 
 class DrivetrainBackwardsParamTest
@@ -970,10 +972,11 @@
   // Since the voltage error compensation is disabled, expect that we will have
   // *failed* to reach our goal.
   drivetrain_status_fetcher_.Fetch();
+  CHECK(drivetrain_status_fetcher_->trajectory_logging() != nullptr);
   const double expected_x =
-      CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())->x();
+      drivetrain_status_fetcher_->trajectory_logging()->x();
   const double expected_y =
-      CHECK_NOTNULL(drivetrain_status_fetcher_->trajectory_logging())->y();
+      drivetrain_status_fetcher_->trajectory_logging()->y();
   const double estimated_x = drivetrain_status_fetcher_->x();
   const double estimated_y = drivetrain_status_fetcher_->y();
   const ::Eigen::Vector2d actual = drivetrain_plant_.GetPosition();
@@ -1497,17 +1500,18 @@
     // We should always just have the past kNumStoredSplines available.
     drivetrain_status_fetcher_.Fetch();
 
-    ASSERT_EQ(expected_splines.size(),
-              CHECK_NOTNULL(drivetrain_status_fetcher_.get()
-                                ->trajectory_logging()
-                                ->available_splines())
-                  ->size());
+    CHECK(drivetrain_status_fetcher_.get()
+              ->trajectory_logging()
+              ->available_splines() != nullptr);
+    ASSERT_EQ(expected_splines.size(), drivetrain_status_fetcher_.get()
+                                           ->trajectory_logging()
+                                           ->available_splines()
+                                           ->size());
     for (size_t ii = 0; ii < expected_splines.size(); ++ii) {
-      EXPECT_EQ(expected_splines[ii],
-                CHECK_NOTNULL(drivetrain_status_fetcher_.get()
-                                  ->trajectory_logging()
-                                  ->available_splines())
-                    ->Get(ii));
+      EXPECT_EQ(expected_splines[ii], drivetrain_status_fetcher_.get()
+                                          ->trajectory_logging()
+                                          ->available_splines()
+                                          ->Get(ii));
     }
   }
 }
@@ -1529,19 +1533,13 @@
   RunFor(chrono::seconds(5));
 
   drivetrain_status_fetcher_.Fetch();
-  EXPECT_TRUE(CHECK_NOTNULL(drivetrain_status_fetcher_->line_follow_logging())
-                  ->frozen());
-  EXPECT_TRUE(CHECK_NOTNULL(drivetrain_status_fetcher_->line_follow_logging())
-                  ->have_target());
-  EXPECT_EQ(
-      1.0,
-      CHECK_NOTNULL(drivetrain_status_fetcher_->line_follow_logging())->x());
-  EXPECT_EQ(
-      1.0,
-      CHECK_NOTNULL(drivetrain_status_fetcher_->line_follow_logging())->y());
-  EXPECT_FLOAT_EQ(
-      M_PI_4, CHECK_NOTNULL(drivetrain_status_fetcher_->line_follow_logging())
-                  ->theta());
+  ASSERT_TRUE(drivetrain_status_fetcher_->line_follow_logging() != nullptr);
+  EXPECT_TRUE(drivetrain_status_fetcher_->line_follow_logging()->frozen());
+  EXPECT_TRUE(drivetrain_status_fetcher_->line_follow_logging()->have_target());
+  EXPECT_EQ(1.0, drivetrain_status_fetcher_->line_follow_logging()->x());
+  EXPECT_EQ(1.0, drivetrain_status_fetcher_->line_follow_logging()->y());
+  EXPECT_FLOAT_EQ(M_PI_4,
+                  drivetrain_status_fetcher_->line_follow_logging()->theta());
 
   // Should have run off the end of the target, running along the y=x line.
   EXPECT_LT(1.0, drivetrain_plant_.GetPosition().x());
diff --git a/frc971/control_loops/drivetrain/hybrid_ekf.h b/frc971/control_loops/drivetrain/hybrid_ekf.h
index 737c179..d3de332 100644
--- a/frc971/control_loops/drivetrain/hybrid_ekf.h
+++ b/frc971/control_loops/drivetrain/hybrid_ekf.h
@@ -741,7 +741,8 @@
     }
     if (obs->h == nullptr) {
       CHECK(obs->make_h != nullptr);
-      obs->h = CHECK_NOTNULL(obs->make_h->MakeExpectedObservations(*state, *P));
+      obs->h = obs->make_h->MakeExpectedObservations(*state, *P);
+      CHECK(obs->h != nullptr);
     }
     CorrectImpl(obs, state, P);
   }
diff --git a/frc971/control_loops/drivetrain/localization/utils.cc b/frc971/control_loops/drivetrain/localization/utils.cc
index c1adb9a..ff6f6c5 100644
--- a/frc971/control_loops/drivetrain/localization/utils.cc
+++ b/frc971/control_loops/drivetrain/localization/utils.cc
@@ -109,7 +109,8 @@
 // verbosity here seems appropriate.
 Eigen::Matrix<double, 4, 4> FlatbufferToTransformationMatrix(
     const frc971::vision::calibration::TransformationMatrix &flatbuffer) {
-  CHECK_EQ(16u, CHECK_NOTNULL(flatbuffer.data())->size());
+  CHECK(flatbuffer.data() != nullptr);
+  CHECK_EQ(16u, flatbuffer.data()->size());
   Eigen::Matrix<double, 4, 4> result;
   result.setIdentity();
   for (int row = 0; row < 4; ++row) {
diff --git a/frc971/control_loops/drivetrain/splinedrivetrain.cc b/frc971/control_loops/drivetrain/splinedrivetrain.cc
index f052a9e..ebe0f64 100644
--- a/frc971/control_loops/drivetrain/splinedrivetrain.cc
+++ b/frc971/control_loops/drivetrain/splinedrivetrain.cc
@@ -79,7 +79,9 @@
 }
 
 void SplineDrivetrain::DeleteCurrentSpline() {
-  DeleteTrajectory(&CHECK_NOTNULL(current_trajectory())->trajectory());
+  const FinishedTrajectory *const trajectory = current_trajectory();
+  CHECK(trajectory != nullptr);
+  DeleteTrajectory(&trajectory->trajectory());
   executing_spline_ = false;
   commanded_spline_.reset();
   current_xva_.setZero();
@@ -95,12 +97,15 @@
       DeleteCurrentSpline();
       return;
     } else {
-      if (executing_spline_ &&
-          CHECK_NOTNULL(current_trajectory())->spline_handle() !=
-              *commanded_spline) {
-        // If we are executing a spline, and the handle has changed, garbage
-        // collect the old spline.
-        DeleteCurrentSpline();
+      if (executing_spline_) {
+        const FinishedTrajectory *const trajectory = current_trajectory();
+        CHECK(trajectory != nullptr);
+
+        if (trajectory->spline_handle() != *commanded_spline) {
+          // If we are executing a spline, and the handle has changed, garbage
+          // collect the old spline.
+          DeleteCurrentSpline();
+        }
       }
     }
   }
@@ -144,8 +149,8 @@
   enable_ = enable;
   if (enable && executing_spline_) {
     ::Eigen::Matrix<double, 2, 1> U_ff = ::Eigen::Matrix<double, 2, 1>::Zero();
-    const FinishedTrajectory *const trajectory =
-        CHECK_NOTNULL(current_trajectory());
+    const FinishedTrajectory *const trajectory = current_trajectory();
+    CHECK(trajectory != nullptr);
     if (!IsAtEnd() && executing_spline_) {
       // TODO(alex): It takes about a cycle for the outputs to propagate to the
       // motors. Consider delaying the output by a cycle.
@@ -258,7 +263,9 @@
     ::Eigen::Matrix<double, 5, 1> goal_state = CurrentGoalState();
     trajectory_logging_builder.add_x(goal_state(0));
     trajectory_logging_builder.add_y(goal_state(1));
-    if (CHECK_NOTNULL(current_trajectory())->drive_spline_backwards()) {
+    const FinishedTrajectory *const trajectory = current_trajectory();
+    CHECK(trajectory != nullptr);
+    if (trajectory->drive_spline_backwards()) {
       trajectory_logging_builder.add_left_velocity(-goal_state(4));
       trajectory_logging_builder.add_right_velocity(-goal_state(3));
       trajectory_logging_builder.add_theta(
@@ -285,10 +292,14 @@
       trajectory_logging_builder.add_current_spline_idx(*commanded_spline_);
     }
   }
-  trajectory_logging_builder.add_distance_remaining(
-      executing_spline_
-          ? CHECK_NOTNULL(current_trajectory())->length() - current_xva_.x()
-          : 0.0);
+  if (executing_spline_) {
+    const FinishedTrajectory *const trajectory = current_trajectory();
+    CHECK(trajectory != nullptr);
+    trajectory_logging_builder.add_distance_remaining(trajectory->length() -
+                                                      current_xva_.x());
+  } else {
+    trajectory_logging_builder.add_distance_remaining(0.0);
+  }
   trajectory_logging_builder.add_available_splines(handles_vector);
   trajectory_logging_builder.add_distance_traveled(
       executing_spline_ ? current_xva_.x() : 0.0);
diff --git a/frc971/control_loops/drivetrain/splinedrivetrain.h b/frc971/control_loops/drivetrain/splinedrivetrain.h
index 24fb66c..09bdc71 100644
--- a/frc971/control_loops/drivetrain/splinedrivetrain.h
+++ b/frc971/control_loops/drivetrain/splinedrivetrain.h
@@ -48,15 +48,23 @@
   // Accessor for the current goal state, pretty much only present for debugging
   // purposes.
   ::Eigen::Matrix<double, 5, 1> CurrentGoalState() const {
-    return executing_spline_ ? CHECK_NOTNULL(current_trajectory())
-                                   ->GoalState(current_xva_(0), current_xva_(1))
-                             : ::Eigen::Matrix<double, 5, 1>::Zero();
+    if (executing_spline_) {
+      const FinishedTrajectory *finished = current_trajectory();
+      CHECK(finished != nullptr);
+      return finished->GoalState(current_xva_(0), current_xva_(1));
+    } else {
+      return ::Eigen::Matrix<double, 5, 1>::Zero();
+    }
   }
 
   bool IsAtEnd() const {
-    return executing_spline_ ? CHECK_NOTNULL(current_trajectory())
-                                   ->is_at_end(current_xva_.block<2, 1>(0, 0))
-                             : true;
+    if (!executing_spline_) {
+      return true;
+    }
+
+    const FinishedTrajectory *finished = current_trajectory();
+    CHECK(finished != nullptr);
+    return finished->is_at_end(current_xva_.block<2, 1>(0, 0));
   }
 
   size_t trajectory_count() const { return trajectories_.size(); }
diff --git a/frc971/control_loops/drivetrain/trajectory.cc b/frc971/control_loops/drivetrain/trajectory.cc
index cf9929f..4db41ee 100644
--- a/frc971/control_loops/drivetrain/trajectory.cc
+++ b/frc971/control_loops/drivetrain/trajectory.cc
@@ -38,9 +38,13 @@
         StateFeedbackLoop<2, 2, 2, double, StateFeedbackHybridPlant<2, 2, 2>,
                           HybridKalman<2, 2, 2>>>
         velocity_drivetrain)
-    : BaseTrajectory(CHECK_NOTNULL(CHECK_NOTNULL(buffer->spline())->spline())
-                         ->constraints(),
-                     config, std::move(velocity_drivetrain)),
+    : BaseTrajectory(
+          [&]() {
+            CHECK(buffer->spline() != nullptr);
+            CHECK(buffer->spline()->spline() != nullptr);
+            return buffer->spline()->spline()->constraints();
+          }(),
+          config, std::move(velocity_drivetrain)),
       buffer_(buffer),
       spline_(*buffer_->spline()) {}
 
@@ -819,8 +823,9 @@
 
 Eigen::Matrix<double, 2, 5> FinishedTrajectory::GainForDistance(
     double distance) const {
+  CHECK(trajectory().gains() != nullptr);
   const flatbuffers::Vector<flatbuffers::Offset<fb::GainPoint>> &gains =
-      *CHECK_NOTNULL(trajectory().gains());
+      *trajectory().gains();
   CHECK_LT(0u, gains.size());
   size_t index = 0;
   for (index = 0; index < gains.size() - 1; ++index) {
diff --git a/frc971/control_loops/hybrid_state_feedback_loop_converters.h b/frc971/control_loops/hybrid_state_feedback_loop_converters.h
index 588a4d5..ffd579c 100644
--- a/frc971/control_loops/hybrid_state_feedback_loop_converters.h
+++ b/frc971/control_loops/hybrid_state_feedback_loop_converters.h
@@ -15,22 +15,28 @@
     number_of_states, number_of_inputs, number_of_outputs>>
 MakeStateFeedbackHybridPlantCoefficients(
     const fbs::StateFeedbackHybridPlantCoefficients &coefficients) {
+  CHECK(coefficients.a_continuous() != nullptr);
+  CHECK(coefficients.b_continuous() != nullptr);
+  CHECK(coefficients.c() != nullptr);
+  CHECK(coefficients.d() != nullptr);
+  CHECK(coefficients.u_max() != nullptr);
+  CHECK(coefficients.u_min() != nullptr);
+  CHECK(coefficients.u_limit_coefficient() != nullptr);
+  CHECK(coefficients.u_limit_constant() != nullptr);
+
   return std::make_unique<StateFeedbackHybridPlantCoefficients<
       number_of_states, number_of_inputs, number_of_outputs>>(
       ToEigenOrDie<number_of_states, number_of_states>(
-          *CHECK_NOTNULL(coefficients.a_continuous())),
+          *coefficients.a_continuous()),
       ToEigenOrDie<number_of_states, number_of_inputs>(
-          *CHECK_NOTNULL(coefficients.b_continuous())),
-      ToEigenOrDie<number_of_outputs, number_of_states>(
-          *CHECK_NOTNULL(coefficients.c())),
-      ToEigenOrDie<number_of_outputs, number_of_inputs>(
-          *CHECK_NOTNULL(coefficients.d())),
-      ToEigenOrDie<number_of_inputs, 1>(*CHECK_NOTNULL(coefficients.u_max())),
-      ToEigenOrDie<number_of_inputs, 1>(*CHECK_NOTNULL(coefficients.u_min())),
+          *coefficients.b_continuous()),
+      ToEigenOrDie<number_of_outputs, number_of_states>(*coefficients.c()),
+      ToEigenOrDie<number_of_outputs, number_of_inputs>(*coefficients.d()),
+      ToEigenOrDie<number_of_inputs, 1>(*coefficients.u_max()),
+      ToEigenOrDie<number_of_inputs, 1>(*coefficients.u_min()),
       ToEigenOrDie<number_of_inputs, number_of_states>(
-          *CHECK_NOTNULL(coefficients.u_limit_coefficient())),
-      ToEigenOrDie<number_of_inputs, 1>(
-          *CHECK_NOTNULL(coefficients.u_limit_constant())),
+          *coefficients.u_limit_coefficient()),
+      ToEigenOrDie<number_of_inputs, 1>(*coefficients.u_limit_constant()),
       coefficients.delayed_u());
 }
 
@@ -39,14 +45,17 @@
                                          number_of_outputs>>
 MakeHybridKalmanCoefficients(
     const fbs::HybridKalmanCoefficients &coefficients) {
+  CHECK(coefficients.q_continuous() != nullptr);
+  CHECK(coefficients.r_continuous() != nullptr);
+  CHECK(coefficients.p_steady_state() != nullptr);
   return std::make_unique<HybridKalmanCoefficients<
       number_of_states, number_of_inputs, number_of_outputs>>(
       ToEigenOrDie<number_of_states, number_of_states>(
-          *CHECK_NOTNULL(coefficients.q_continuous())),
+          *coefficients.q_continuous()),
       ToEigenOrDie<number_of_outputs, number_of_outputs>(
-          *CHECK_NOTNULL(coefficients.r_continuous())),
+          *coefficients.r_continuous()),
       ToEigenOrDie<number_of_states, number_of_states>(
-          *CHECK_NOTNULL(coefficients.p_steady_state())),
+          *coefficients.p_steady_state()),
       coefficients.delayed_u());
 }
 template <int number_of_states, int number_of_inputs, int number_of_outputs>
diff --git a/frc971/control_loops/python/test_drivetrain/drivetrain_json_test.cc b/frc971/control_loops/python/test_drivetrain/drivetrain_json_test.cc
index 8c4d95f..c4a4ebe 100644
--- a/frc971/control_loops/python/test_drivetrain/drivetrain_json_test.cc
+++ b/frc971/control_loops/python/test_drivetrain/drivetrain_json_test.cc
@@ -33,8 +33,9 @@
       "frc971/control_loops/python/test_drivetrain/"
       "drivetrain_dog_motor_plant.json");
 
-  StateFeedbackLoop<4, 2, 2> json_loop = MakeStateFeedbackLoop<4, 2, 2>(
-      *CHECK_NOTNULL(coeffs.message().drivetrain_loop()));
+  CHECK(coeffs.message().drivetrain_loop() != nullptr);
+  StateFeedbackLoop<4, 2, 2> json_loop =
+      MakeStateFeedbackLoop<4, 2, 2>(*coeffs.message().drivetrain_loop());
   for (size_t index = 0; index < 4; ++index) {
     ASSERT_TRUE(coeffs.span().size() > 0u);
     made_loop.set_index(index);
@@ -80,8 +81,9 @@
       "frc971/control_loops/python/test_drivetrain/"
       "hybrid_velocity_drivetrain.json");
 
+  CHECK(coeffs.message().hybrid_velocity_drivetrain_loop() != nullptr);
   HybridLoop json_loop = MakeHybridStateFeedbackLoop<2, 2, 2>(
-      *CHECK_NOTNULL(coeffs.message().hybrid_velocity_drivetrain_loop()));
+      *coeffs.message().hybrid_velocity_drivetrain_loop());
   for (size_t index = 0; index < 4; ++index) {
     ASSERT_TRUE(coeffs.span().size() > 0u);
     made_loop.set_index(index);
diff --git a/frc971/control_loops/state_feedback_loop_converters.h b/frc971/control_loops/state_feedback_loop_converters.h
index 062257d..5e0117a 100644
--- a/frc971/control_loops/state_feedback_loop_converters.h
+++ b/frc971/control_loops/state_feedback_loop_converters.h
@@ -17,22 +17,26 @@
     number_of_states, number_of_inputs, number_of_outputs>>
 MakeStateFeedbackPlantCoefficients(
     const fbs::StateFeedbackPlantCoefficients &coefficients) {
+  CHECK(coefficients.a() != nullptr);
+  CHECK(coefficients.b() != nullptr);
+  CHECK(coefficients.c() != nullptr);
+  CHECK(coefficients.d() != nullptr);
+  CHECK(coefficients.u_max() != nullptr);
+  CHECK(coefficients.u_min() != nullptr);
+  CHECK(coefficients.u_limit_coefficient() != nullptr);
+  CHECK(coefficients.u_limit_constant() != nullptr);
+
   return std::make_unique<StateFeedbackPlantCoefficients<
       number_of_states, number_of_inputs, number_of_outputs>>(
-      ToEigenOrDie<number_of_states, number_of_states>(
-          *CHECK_NOTNULL(coefficients.a())),
-      ToEigenOrDie<number_of_states, number_of_inputs>(
-          *CHECK_NOTNULL(coefficients.b())),
-      ToEigenOrDie<number_of_outputs, number_of_states>(
-          *CHECK_NOTNULL(coefficients.c())),
-      ToEigenOrDie<number_of_outputs, number_of_inputs>(
-          *CHECK_NOTNULL(coefficients.d())),
-      ToEigenOrDie<number_of_inputs, 1>(*CHECK_NOTNULL(coefficients.u_max())),
-      ToEigenOrDie<number_of_inputs, 1>(*CHECK_NOTNULL(coefficients.u_min())),
+      ToEigenOrDie<number_of_states, number_of_states>(*coefficients.a()),
+      ToEigenOrDie<number_of_states, number_of_inputs>(*coefficients.b()),
+      ToEigenOrDie<number_of_outputs, number_of_states>(*coefficients.c()),
+      ToEigenOrDie<number_of_outputs, number_of_inputs>(*coefficients.d()),
+      ToEigenOrDie<number_of_inputs, 1>(*coefficients.u_max()),
+      ToEigenOrDie<number_of_inputs, 1>(*coefficients.u_min()),
       ToEigenOrDie<number_of_inputs, number_of_states>(
-          *CHECK_NOTNULL(coefficients.u_limit_coefficient())),
-      ToEigenOrDie<number_of_inputs, 1>(
-          *CHECK_NOTNULL(coefficients.u_limit_constant())),
+          *coefficients.u_limit_coefficient()),
+      ToEigenOrDie<number_of_inputs, 1>(*coefficients.u_limit_constant()),
       std::chrono::nanoseconds(coefficients.dt()), coefficients.delayed_u());
 }
 
@@ -41,12 +45,12 @@
     number_of_states, number_of_inputs, number_of_outputs>>
 MakeStateFeedbackControllerCoefficients(
     const fbs::StateFeedbackControllerCoefficients &coefficients) {
+  CHECK(coefficients.k() != nullptr);
+  CHECK(coefficients.kff() != nullptr);
   return std::make_unique<StateFeedbackControllerCoefficients<
       number_of_states, number_of_inputs, number_of_outputs>>(
-      ToEigenOrDie<number_of_inputs, number_of_states>(
-          *CHECK_NOTNULL(coefficients.k())),
-      ToEigenOrDie<number_of_inputs, number_of_states>(
-          *CHECK_NOTNULL(coefficients.kff())));
+      ToEigenOrDie<number_of_inputs, number_of_states>(*coefficients.k()),
+      ToEigenOrDie<number_of_inputs, number_of_states>(*coefficients.kff()));
 }
 
 template <int number_of_states, int number_of_inputs, int number_of_outputs>
@@ -54,14 +58,15 @@
     number_of_states, number_of_inputs, number_of_outputs>>
 MakeStateFeedbackObserverCoefficients(
     const fbs::StateFeedbackObserverCoefficients &coefficients) {
+  CHECK(coefficients.kalman_gain() != nullptr);
+  CHECK(coefficients.q() != nullptr);
+  CHECK(coefficients.r() != nullptr);
   return std::make_unique<StateFeedbackObserverCoefficients<
       number_of_states, number_of_inputs, number_of_outputs>>(
       ToEigenOrDie<number_of_states, number_of_outputs>(
-          *CHECK_NOTNULL(coefficients.kalman_gain())),
-      ToEigenOrDie<number_of_states, number_of_states>(
-          *CHECK_NOTNULL(coefficients.q())),
-      ToEigenOrDie<number_of_outputs, number_of_outputs>(
-          *CHECK_NOTNULL(coefficients.r())),
+          *coefficients.kalman_gain()),
+      ToEigenOrDie<number_of_states, number_of_states>(*coefficients.q()),
+      ToEigenOrDie<number_of_outputs, number_of_outputs>(*coefficients.r()),
       coefficients.delayed_u());
 }
 
diff --git a/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h b/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
index c084047..811e8e5 100644
--- a/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
+++ b/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
@@ -80,8 +80,8 @@
         range(frc971::constants::Range::FromFlatbuffer(common->range())),
         zeroing_constants(aos::UnpackFlatbuffer(zeroing)),
         make_integral_loop([this]() {
-          return MakeStateFeedbackLoop<3, 1, 1>(
-              *CHECK_NOTNULL(loop_params->message().loop()));
+          CHECK(loop_params->message().loop() != nullptr);
+          return MakeStateFeedbackLoop<3, 1, 1>(*loop_params->message().loop());
         }),
         loop_params(std::make_shared<aos::FlatbufferDetachedBuffer<
                         StaticZeroingSingleDOFProfiledSubsystemCommonParams>>(
@@ -280,7 +280,7 @@
     Profile>::Correct(const StaticZeroingSingleDOFProfiledSubsystemGoal *goal,
                       const typename ZeroingEstimator::Position *position,
                       bool disabled) {
-  CHECK_NOTNULL(position);
+  CHECK(position != nullptr);
   profiled_subsystem_.Correct(*position);
 
   if (profiled_subsystem_.error()) {
@@ -444,7 +444,7 @@
 StaticZeroingSingleDOFProfiledSubsystem<
     ZeroingEstimator, ProfiledJointStatus, SubsystemParams,
     Profile>::MakeStatus(flatbuffers::FlatBufferBuilder *status_fbb) {
-  CHECK_NOTNULL(status_fbb);
+  CHECK(status_fbb != nullptr);
 
   typename ProfiledJointStatus::Builder status_builder =
       profiled_subsystem_
diff --git a/frc971/image_streamer/image_streamer.cc b/frc971/image_streamer/image_streamer.cc
index 6c9a732..b89adc0 100644
--- a/frc971/image_streamer/image_streamer.cc
+++ b/frc971/image_streamer/image_streamer.cc
@@ -175,9 +175,10 @@
 
     GST_BUFFER_PTS(buffer) = image.monotonic_timestamp_ns();
 
-    GstCaps *caps = CHECK_NOTNULL(gst_caps_new_simple(
+    GstCaps *caps = gst_caps_new_simple(
         "video/x-raw", "width", G_TYPE_INT, image.cols(), "height", G_TYPE_INT,
-        image.rows(), "format", G_TYPE_STRING, "YUY2", nullptr));
+        image.rows(), "format", G_TYPE_STRING, "YUY2", nullptr);
+    CHECK(caps != nullptr);
 
     GstSample *sample = gst_sample_new(buffer, caps, nullptr, nullptr);
 
@@ -314,7 +315,8 @@
   }
 
   if (sender_.valid()) {
-    const GstCaps *caps = CHECK_NOTNULL(gst_sample_get_caps(sample));
+    const GstCaps *caps = gst_sample_get_caps(sample);
+    CHECK(caps != nullptr);
     CHECK_GT(gst_caps_get_size(caps), 0U);
     const GstStructure *str = gst_caps_get_structure(caps, 0);
 
@@ -324,7 +326,8 @@
     CHECK(gst_structure_get_int(str, "width", &width));
     CHECK(gst_structure_get_int(str, "height", &height));
 
-    GstBuffer *buffer = CHECK_NOTNULL(gst_sample_get_buffer(sample));
+    GstBuffer *buffer = gst_sample_get_buffer(sample);
+    CHECK(buffer != nullptr);
 
     const gsize size = gst_buffer_get_size(buffer);
 
@@ -410,7 +413,7 @@
   {
     GstObject *ice = nullptr;
     g_object_get(G_OBJECT(webrtcbin_), "ice-agent", &ice, nullptr);
-    CHECK_NOTNULL(ice);
+    CHECK(ice != nullptr);
 
     g_object_set(ice, "min-rtp-port", FLAGS_min_port, "max-rtp-port",
                  FLAGS_max_port, nullptr);
@@ -419,7 +422,7 @@
     {
       GstObject *nice = nullptr;
       g_object_get(ice, "agent", &nice, nullptr);
-      CHECK_NOTNULL(nice);
+      CHECK(nice != nullptr);
 
       g_object_set(nice, "upnp", false, nullptr);
       g_object_unref(nice);
diff --git a/frc971/imu_fdcan/dual_imu_blender_lib.cc b/frc971/imu_fdcan/dual_imu_blender_lib.cc
index 6099844..d390102 100644
--- a/frc971/imu_fdcan/dual_imu_blender_lib.cc
+++ b/frc971/imu_fdcan/dual_imu_blender_lib.cc
@@ -41,7 +41,8 @@
           dual_imu_blender_status_sender_.MakeStaticBuilder();
 
   frc971::IMUValuesStatic *imu_values =
-      CHECK_NOTNULL(imu_values_batch_builder_->add_readings()->emplace_back());
+      imu_values_batch_builder_->add_readings()->emplace_back();
+  CHECK(imu_values != nullptr);
 
   imu_values->set_pico_timestamp_us(dual_imu->board_timestamp_us());
   imu_values->set_monotonic_timestamp_ns(dual_imu->kernel_timestamp());
diff --git a/frc971/vision/charuco_lib.cc b/frc971/vision/charuco_lib.cc
index d006e2d..71c2ff6 100644
--- a/frc971/vision/charuco_lib.cc
+++ b/frc971/vision/charuco_lib.cc
@@ -45,6 +45,7 @@
 CameraCalibration::CameraCalibration(
     const calibration::CameraCalibration *calibration)
     : intrinsics_([calibration]() {
+        CHECK(calibration != nullptr);
         const cv::Mat result(3, 3, CV_32F,
                              const_cast<void *>(static_cast<const void *>(
                                  calibration->intrinsics()->data())));
@@ -291,7 +292,7 @@
     const TargetType target_type)
     : event_loop_(nullptr),
       target_type_(target_type),
-      calibration_(CHECK_NOTNULL(calibration)) {
+      calibration_(calibration) {
   VLOG(2) << "Configuring CharucoExtractor without event_loop";
   SetupTargetData();
   VLOG(2) << "Camera matrix:\n" << calibration_.CameraIntrinsics();
@@ -310,7 +311,7 @@
     : event_loop_(event_loop),
       target_type_(target_type),
       image_channel_(image_channel),
-      calibration_(CHECK_NOTNULL(calibration)),
+      calibration_(calibration),
       handle_charuco_(std::move(handle_charuco_fn)) {
   SetupTargetData();
 
diff --git a/frc971/vision/target_mapper.cc b/frc971/vision/target_mapper.cc
index 57ab6e4..f245f37 100644
--- a/frc971/vision/target_mapper.cc
+++ b/frc971/vision/target_mapper.cc
@@ -467,7 +467,7 @@
 
 // Taken from ceres/examples/slam/pose_graph_3d/pose_graph_3d.cc
 bool TargetMapper::SolveOptimizationProblem(ceres::Problem *problem) {
-  CHECK_NOTNULL(problem);
+  CHECK(problem != nullptr);
 
   ceres::Solver::Options options;
   options.max_num_iterations = FLAGS_max_num_iterations;
diff --git a/frc971/vision/v4l2_reader.h b/frc971/vision/v4l2_reader.h
index a3d6252..4906d8e 100644
--- a/frc971/vision/v4l2_reader.h
+++ b/frc971/vision/v4l2_reader.h
@@ -107,8 +107,9 @@
     }
 
     absl::Span<const char> DataSpan(size_t image_size) {
-      return absl::Span<const char>(
-          reinterpret_cast<char *>(CHECK_NOTNULL(data_pointer)), image_size);
+      CHECK(data_pointer != nullptr);
+      return absl::Span<const char>(reinterpret_cast<char *>(data_pointer),
+                                    image_size);
     }
 
     aos::Sender<CameraImage> sender;
diff --git a/frc971/wpilib/swerve/swerve_module.h b/frc971/wpilib/swerve/swerve_module.h
index c01df24..1a16dce 100644
--- a/frc971/wpilib/swerve/swerve_module.h
+++ b/frc971/wpilib/swerve/swerve_module.h
@@ -76,7 +76,8 @@
 // Represents all the modules in a swerve drivetrain.
 struct SwerveModules {
   void PopulateFalconsVector(std::vector<std::shared_ptr<TalonFX>> *falcons) {
-    CHECK_NOTNULL(falcons)->push_back(front_left->rotation);
+    CHECK(falcons != nullptr);
+    falcons->push_back(front_left->rotation);
     falcons->push_back(front_left->translation);
 
     falcons->push_back(front_right->rotation);
diff --git a/frc971/wpilib/talonfx.cc b/frc971/wpilib/talonfx.cc
index 152339e..4338cfd 100644
--- a/frc971/wpilib/talonfx.cc
+++ b/frc971/wpilib/talonfx.cc
@@ -21,7 +21,7 @@
   // device temp is not timesynced so don't add it to the list of signals
   device_temp_.SetUpdateFrequency(kCANUpdateFreqHz);
 
-  CHECK_NOTNULL(signals);
+  CHECK(signals != nullptr);
 
   supply_voltage_.SetUpdateFrequency(kCANUpdateFreqHz);
   signals->push_back(&supply_voltage_);
diff --git a/y2019/joystick_reader.cc b/y2019/joystick_reader.cc
index b44d084..40e8708 100644
--- a/y2019/joystick_reader.cc
+++ b/y2019/joystick_reader.cc
@@ -244,9 +244,10 @@
 
       superstructure_goal_offset = superstructure_goal_builder.Finish();
     }
-    superstructure::Goal *mutable_superstructure_goal = CHECK_NOTNULL(
+    superstructure::Goal *mutable_superstructure_goal =
         GetMutableTemporaryPointer(*main_superstructure_goal_builder.fbb(),
-                                   superstructure_goal_offset));
+                                   superstructure_goal_offset);
+    CHECK(mutable_superstructure_goal != nullptr);
 
     {
       auto builder = target_selector_hint_sender_.MakeBuilder();
@@ -585,18 +586,17 @@
       AOS_LOG(INFO, "Releasing due to button\n");
     }
 
+    auto mutable_suction = mutable_superstructure_goal->mutable_suction();
+    CHECK(mutable_suction != nullptr);
     if (switch_ball_) {
-      CHECK_NOTNULL(mutable_superstructure_goal->mutable_suction())
-          ->mutate_gamepiece_mode(0);
+      mutable_suction->mutate_gamepiece_mode(0);
     } else {
-      CHECK_NOTNULL(mutable_superstructure_goal->mutable_suction())
-          ->mutate_gamepiece_mode(1);
+      mutable_suction->mutate_gamepiece_mode(1);
     }
 
     vision_control_.set_flip_image(elevator_wrist_pos_.wrist < 0);
 
-    CHECK_NOTNULL(mutable_superstructure_goal->mutable_suction())
-        ->mutate_grab_piece(grab_piece_);
+    mutable_suction->mutate_grab_piece(grab_piece_);
 
     mutable_superstructure_goal->mutable_elevator()->mutate_unsafe_goal(
         elevator_wrist_pos_.elevator);
diff --git a/y2020/control_loops/drivetrain/localizer.cc b/y2020/control_loops/drivetrain/localizer.cc
index fabbb8e..0943b28 100644
--- a/y2020/control_loops/drivetrain/localizer.cc
+++ b/y2020/control_loops/drivetrain/localizer.cc
@@ -14,7 +14,8 @@
 // appropriate.
 Eigen::Matrix<float, 4, 4> FlatbufferToTransformationMatrix(
     const frc971::vision::sift::TransformationMatrix &flatbuffer) {
-  CHECK_EQ(16u, CHECK_NOTNULL(flatbuffer.data())->size());
+  CHECK(flatbuffer.data() != nullptr);
+  CHECK_EQ(16u, flatbuffer.data()->size());
   Eigen::Matrix<float, 4, 4> result;
   result.setIdentity();
   for (int row = 0; row < 4; ++row) {
diff --git a/y2020/control_loops/drivetrain/localizer_test.cc b/y2020/control_loops/drivetrain/localizer_test.cc
index ca25137..e509241 100644
--- a/y2020/control_loops/drivetrain/localizer_test.cc
+++ b/y2020/control_loops/drivetrain/localizer_test.cc
@@ -215,7 +215,8 @@
     // Run for enough time to allow the gyro/imu zeroing code to run.
     RunFor(std::chrono::seconds(15));
     CHECK(drivetrain_status_fetcher_.Fetch());
-    EXPECT_TRUE(CHECK_NOTNULL(drivetrain_status_fetcher_->zeroing())->zeroed());
+    CHECK(drivetrain_status_fetcher_->zeroing() != nullptr);
+    EXPECT_TRUE(drivetrain_status_fetcher_->zeroing()->zeroed());
   }
 
   virtual ~LocalizedDrivetrainTest() override {}
diff --git a/y2022/localizer/localizer.cc b/y2022/localizer/localizer.cc
index ab91db3..c4ccf85 100644
--- a/y2022/localizer/localizer.cc
+++ b/y2022/localizer/localizer.cc
@@ -489,8 +489,8 @@
     const OldPosition &state,
     const frc971::vision::calibration::CameraCalibration *calibration,
     std::optional<RejectionReason> *rejection_reason) const {
-  CHECK_NOTNULL(rejection_reason);
-  CHECK_NOTNULL(calibration);
+  CHECK(rejection_reason != nullptr);
+  CHECK(calibration != nullptr);
   // Per the CameraCalibration specification, we can actually determine whether
   // the camera is the turret camera just from the presence of the
   // turret_extrinsics member.
diff --git a/y2023/control_loops/drivetrain/target_selector.cc b/y2023/control_loops/drivetrain/target_selector.cc
index bc1fb90..22a5140 100644
--- a/y2023/control_loops/drivetrain/target_selector.cc
+++ b/y2023/control_loops/drivetrain/target_selector.cc
@@ -78,7 +78,7 @@
       [possible_grids, hint]() {
         aos::SizedArray<const localizer::ScoringRow *, 3> rows;
         for (const localizer::ScoringGrid *grid : possible_grids) {
-          CHECK_NOTNULL(grid);
+          CHECK(grid != nullptr);
           switch (hint->row()) {
             case RowSelectionHint::BOTTOM:
               rows.push_back(grid->bottom());
@@ -95,7 +95,7 @@
       }();
   aos::SizedArray<const frc971::vision::Position *, 3> positions;
   for (const localizer::ScoringRow *row : possible_rows) {
-    CHECK_NOTNULL(row);
+    CHECK(row != nullptr);
     switch (hint->spot()) {
       case SpotSelectionHint::LEFT:
         positions.push_back(row->left_cone());
diff --git a/y2023/control_loops/superstructure/superstructure.cc b/y2023/control_loops/superstructure/superstructure.cc
index 0ee1061..bfb7a9d 100644
--- a/y2023/control_loops/superstructure/superstructure.cc
+++ b/y2023/control_loops/superstructure/superstructure.cc
@@ -134,10 +134,14 @@
   if (reading > kInvalidReading || !std::isfinite(reading)) {
     return std::nullopt;
   }
-  const TimeOfFlight *calibration = CHECK_NOTNULL(
-      CHECK_NOTNULL(constants_fetcher_.constants().robot())->tof());
+  auto robot = constants_fetcher_.constants().robot();
+  CHECK(robot != nullptr);
+  const TimeOfFlight *calibration =
+      constants_fetcher_.constants().robot()->tof();
+  CHECK(calibration != nullptr);
   // TODO(james): Use a generic interpolation table class.
-  auto table = CHECK_NOTNULL(calibration->interpolation_table());
+  auto table = calibration->interpolation_table();
+  CHECK(table != nullptr);
   CHECK_EQ(2u, table->size());
   double x1 = table->Get(0)->tof_reading();
   double x2 = table->Get(1)->tof_reading();
diff --git a/y2023/joystick_reader.cc b/y2023/joystick_reader.cc
index 45418bc..6e62c5b 100644
--- a/y2023/joystick_reader.cc
+++ b/y2023/joystick_reader.cc
@@ -533,7 +533,8 @@
       auto builder = target_selector_hint_sender_.MakeBuilder();
       auto hint_builder = builder.MakeBuilder<TargetSelectorHint>();
       hint_builder.add_substation_pickup(true);
-      hint_builder.add_robot_side(CHECK_NOTNULL(current_setpoint_)->side);
+      CHECK(current_setpoint_ != nullptr);
+      hint_builder.add_robot_side(current_setpoint_->side);
       if (builder.Send(hint_builder.Finish()) != aos::RawSender::Error::kOk) {
         AOS_LOG(ERROR, "Sending target selector hint failed.\n");
       }
@@ -542,7 +543,8 @@
       auto hint_builder = builder.MakeBuilder<TargetSelectorHint>();
       hint_builder.add_row(placing_row.value());
       hint_builder.add_spot(placing_spot.value());
-      hint_builder.add_robot_side(CHECK_NOTNULL(current_setpoint_)->side);
+      CHECK(current_setpoint_ != nullptr);
+      hint_builder.add_robot_side(current_setpoint_->side);
       if (builder.Send(hint_builder.Finish()) != aos::RawSender::Error::kOk) {
         AOS_LOG(ERROR, "Sending target selector hint failed.\n");
       }
diff --git a/y2023/localizer/localizer.cc b/y2023/localizer/localizer.cc
index 6f9a16b..a00ebe6 100644
--- a/y2023/localizer/localizer.cc
+++ b/y2023/localizer/localizer.cc
@@ -264,12 +264,12 @@
 
   switch (utils_.Alliance()) {
     case aos::Alliance::kRed:
-      ignore_tags =
-          CHECK_NOTNULL(constants_fetcher_.constants().ignore_targets()->red());
+      ignore_tags = constants_fetcher_.constants().ignore_targets()->red();
+      CHECK(ignore_tags != nullptr);
       break;
     case aos::Alliance::kBlue:
-      ignore_tags = CHECK_NOTNULL(
-          constants_fetcher_.constants().ignore_targets()->blue());
+      ignore_tags = constants_fetcher_.constants().ignore_targets()->blue();
+      CHECK(ignore_tags != nullptr);
       break;
     case aos::Alliance::kInvalid:
       return true;
diff --git a/y2023/wpilib_interface.cc b/y2023/wpilib_interface.cc
index 492d44b..d0d952c 100644
--- a/y2023/wpilib_interface.cc
+++ b/y2023/wpilib_interface.cc
@@ -133,7 +133,7 @@
     // device temp is not timesynced so don't add it to the list of signals
     device_temp_.SetUpdateFrequency(kCANUpdateFreqHz);
 
-    CHECK_NOTNULL(signals);
+    CHECK(signals != nullptr);
 
     supply_voltage_.SetUpdateFrequency(kCANUpdateFreqHz);
     signals->push_back(&supply_voltage_);
diff --git a/y2023_bot3/wpilib_interface.cc b/y2023_bot3/wpilib_interface.cc
index 1dd8efd..1f0c003 100644
--- a/y2023_bot3/wpilib_interface.cc
+++ b/y2023_bot3/wpilib_interface.cc
@@ -113,7 +113,7 @@
     // device temp is not timesynced so don't add it to the list of signals
     device_temp_.SetUpdateFrequency(kCANUpdateFreqHz);
 
-    CHECK_NOTNULL(signals);
+    CHECK(signals != nullptr);
 
     supply_voltage_.SetUpdateFrequency(kCANUpdateFreqHz);
     signals->push_back(&supply_voltage_);
diff --git a/y2024/autonomous/autonomous_actor.cc b/y2024/autonomous/autonomous_actor.cc
index 0f70292..83cf5b1 100644
--- a/y2024/autonomous/autonomous_actor.cc
+++ b/y2024/autonomous/autonomous_actor.cc
@@ -51,8 +51,10 @@
           event_loop
               ->MakeFetcher<::y2024::control_loops::superstructure::Status>(
                   "/superstructure")),
-      robot_constants_(CHECK_NOTNULL(robot_constants)),
-      auto_splines_() {}
+      robot_constants_(robot_constants),
+      auto_splines_() {
+  CHECK(robot_constants_ != nullptr);
+}
 
 void AutonomousActor::Replan() {
   AutonomousMode mode = robot_constants_->common()->autonomous_mode();
diff --git a/y2024/control_loops/drivetrain/drivetrain_base.cc b/y2024/control_loops/drivetrain/drivetrain_base.cc
index 79d35e1..dd4f33c 100644
--- a/y2024/control_loops/drivetrain/drivetrain_base.cc
+++ b/y2024/control_loops/drivetrain/drivetrain_base.cc
@@ -11,9 +11,10 @@
 const frc971::control_loops::drivetrain::DrivetrainConfig<double>
 GetDrivetrainConfig(aos::EventLoop *event_loop) {
   frc971::constants::ConstantsFetcher<Constants> constants_fetcher(event_loop);
+  CHECK(constants_fetcher.constants().common() != nullptr);
+  CHECK(constants_fetcher.constants().common()->drivetrain() != nullptr);
   return frc971::control_loops::drivetrain::DrivetrainConfig<double>::
-      FromFlatbuffer(
-          *CHECK_NOTNULL(constants_fetcher.constants().common()->drivetrain()));
+      FromFlatbuffer(*constants_fetcher.constants().common()->drivetrain());
 };
 
 }  // namespace y2024::control_loops::drivetrain
diff --git a/y2024/control_loops/superstructure/aiming.cc b/y2024/control_loops/superstructure/aiming.cc
index d8d336f..b53dbb5 100644
--- a/y2024/control_loops/superstructure/aiming.cc
+++ b/y2024/control_loops/superstructure/aiming.cc
@@ -11,7 +11,10 @@
 Aimer::Aimer(aos::EventLoop *event_loop,
              const y2024::Constants *robot_constants)
     : event_loop_(event_loop),
-      robot_constants_(CHECK_NOTNULL(robot_constants)),
+      robot_constants_([&]() {
+        CHECK(robot_constants != nullptr);
+        return robot_constants;
+      }()),
       drivetrain_config_(
           frc971::control_loops::drivetrain::DrivetrainConfig<double>::
               FromFlatbuffer(*robot_constants_->common()->drivetrain())),
@@ -58,7 +61,7 @@
   } else {
     received_joystick_state_ = true;
 
-    CHECK_NOTNULL(joystick_state_fetcher_.get());
+    CHECK(joystick_state_fetcher_.get() != nullptr);
     alliance = joystick_state_fetcher_->alliance();
   }
 
diff --git a/y2024/control_loops/superstructure/superstructure.cc b/y2024/control_loops/superstructure/superstructure.cc
index a485943..7f7da4f 100644
--- a/y2024/control_loops/superstructure/superstructure.cc
+++ b/y2024/control_loops/superstructure/superstructure.cc
@@ -36,7 +36,7 @@
     : frc971::controls::ControlLoop<Goal, Position, Status, Output>(event_loop,
                                                                     name),
       constants_fetcher_(event_loop),
-      robot_constants_(CHECK_NOTNULL(&constants_fetcher_.constants())),
+      robot_constants_(&constants_fetcher_.constants()),
       drivetrain_status_fetcher_(
           event_loop->MakeFetcher<frc971::control_loops::drivetrain::Status>(
               "/drivetrain")),
diff --git a/y2024/control_loops/superstructure/superstructure_lib_test.cc b/y2024/control_loops/superstructure/superstructure_lib_test.cc
index 59398ab..719a29b 100644
--- a/y2024/control_loops/superstructure/superstructure_lib_test.cc
+++ b/y2024/control_loops/superstructure/superstructure_lib_test.cc
@@ -312,8 +312,7 @@
         superstructure_(superstructure_event_loop.get()),
         test_event_loop_(MakeEventLoop("test", roborio_)),
         constants_fetcher_(test_event_loop_.get()),
-        simulated_robot_constants_(
-            CHECK_NOTNULL(&constants_fetcher_.constants())),
+        simulated_robot_constants_(&constants_fetcher_.constants()),
         superstructure_goal_fetcher_(
             test_event_loop_->MakeFetcher<Goal>("/superstructure")),
         superstructure_goal_sender_(
diff --git a/y2024/joystick_reader.cc b/y2024/joystick_reader.cc
index 711f9d2..88bf441 100644
--- a/y2024/joystick_reader.cc
+++ b/y2024/joystick_reader.cc
@@ -82,7 +82,9 @@
         superstructure_status_fetcher_(
             event_loop->MakeFetcher<control_loops::superstructure::Status>(
                 "/superstructure")),
-        robot_constants_(CHECK_NOTNULL(robot_constants)) {}
+        robot_constants_(robot_constants) {
+    CHECK(robot_constants_ != nullptr);
+  }
 
   void AutoEnded() override { AOS_LOG(INFO, "Auto ended.\n"); }
 
diff --git a/y2024/localizer/localizer.cc b/y2024/localizer/localizer.cc
index d73d171..90423ca 100644
--- a/y2024/localizer/localizer.cc
+++ b/y2024/localizer/localizer.cc
@@ -174,10 +174,12 @@
 Localizer::Localizer(aos::EventLoop *event_loop)
     : event_loop_(event_loop),
       constants_fetcher_(event_loop),
-      dt_config_(
-          frc971::control_loops::drivetrain::DrivetrainConfig<double>::
-              FromFlatbuffer(*CHECK_NOTNULL(
-                  constants_fetcher_.constants().common()->drivetrain()))),
+      dt_config_(frc971::control_loops::drivetrain::DrivetrainConfig<
+                 double>::FromFlatbuffer(*[&]() {
+        CHECK(constants_fetcher_.constants().common() != nullptr);
+        CHECK(constants_fetcher_.constants().common()->drivetrain() != nullptr);
+        return constants_fetcher_.constants().common()->drivetrain();
+      }())),
       cameras_(MakeCameras(constants_fetcher_.constants(), event_loop)),
       target_poses_(GetTargetLocations(constants_fetcher_.constants())),
       down_estimator_(dt_config_),
@@ -214,8 +216,9 @@
 
   for (size_t camera_index = 0; camera_index < kNumCameras; ++camera_index) {
     const std::string_view channel_name = kDetectionChannels.at(camera_index);
-    const aos::Channel *const channel = CHECK_NOTNULL(
-        event_loop->GetChannel<frc971::vision::TargetMap>(channel_name));
+    const aos::Channel *const channel =
+        event_loop->GetChannel<frc971::vision::TargetMap>(channel_name);
+    CHECK(channel != nullptr);
     event_loop->MakeWatcher(
         channel_name, [this, channel,
                        camera_index](const frc971::vision::TargetMap &targets) {
@@ -360,12 +363,14 @@
 
   switch (utils_.Alliance()) {
     case aos::Alliance::kRed:
-      ignore_tags = CHECK_NOTNULL(
-          constants_fetcher_.constants().common()->ignore_targets()->red());
+      ignore_tags =
+          constants_fetcher_.constants().common()->ignore_targets()->red();
+      CHECK(ignore_tags != nullptr);
       break;
     case aos::Alliance::kBlue:
-      ignore_tags = CHECK_NOTNULL(
-          constants_fetcher_.constants().common()->ignore_targets()->blue());
+      ignore_tags =
+          constants_fetcher_.constants().common()->ignore_targets()->blue();
+      CHECK(ignore_tags != nullptr);
       break;
     case aos::Alliance::kInvalid:
       return false;
diff --git a/y2024/wpilib_interface.cc b/y2024/wpilib_interface.cc
index 30d1549..c8328da 100644
--- a/y2024/wpilib_interface.cc
+++ b/y2024/wpilib_interface.cc
@@ -123,7 +123,7 @@
   SensorReader(::aos::ShmEventLoop *event_loop,
                const Constants *robot_constants)
       : ::frc971::wpilib::SensorReader(event_loop),
-        robot_constants_(CHECK_NOTNULL(robot_constants)),
+        robot_constants_(robot_constants),
         auto_mode_sender_(
             event_loop->MakeSender<::frc971::autonomous::AutonomousMode>(
                 "/autonomous")),
@@ -505,7 +505,8 @@
                     drivetrain_can_position_sender.MakeStaticBuilder();
 
             auto drivetrain_falcon_vector =
-                CHECK_NOTNULL(drivetrain_can_builder->add_talonfxs());
+                drivetrain_can_builder->add_talonfxs();
+            CHECK(drivetrain_falcon_vector != nullptr);
 
             for (auto talonfx : drivetrain_krakens) {
               talonfx->SerializePosition(
@@ -678,7 +679,8 @@
                   drivetrain_can_position_sender.MakeStaticBuilder();
 
           auto drivetrain_falcon_vector =
-              CHECK_NOTNULL(drivetrain_can_builder->add_talonfxs());
+              drivetrain_can_builder->add_talonfxs();
+          CHECK(drivetrain_falcon_vector != nullptr);
 
           for (auto talonfx : drivetrain_talonfxs) {
             talonfx->SerializePosition(