diff --git a/source/RobotAPI/libraries/armem/error/ArMemError.cpp b/source/RobotAPI/libraries/armem/error/ArMemError.cpp
index de7edf68c108b10299ef466688297af7d9b38ddc..b6cac6b7c685af1273c670eca1dcb2f25ce644e0 100644
--- a/source/RobotAPI/libraries/armem/error/ArMemError.cpp
+++ b/source/RobotAPI/libraries/armem/error/ArMemError.cpp
@@ -14,6 +14,27 @@ namespace armarx::armem::error
     }
 
 
+    InvalidArgument::InvalidArgument(const std::string& argument, const std::string& function, const std::string& message) :
+        ArMemError(makeMsg(argument, function, message))
+    {
+    }
+
+    std::string InvalidArgument::makeMsg(const std::string& argument, const std::string& function, const std::string& message)
+    {
+        std::stringstream ss;
+        ss << "Invalid value for argument '" << argument << "' in function " << function << "()";
+        if (message.empty())
+        {
+            ss << ".";
+        }
+        else
+        {
+            ss << ":\n" << message;
+        }
+        return ss.str();
+    }
+
+
     StorageNameMismatch::StorageNameMismatch(const std::string& expectedName,
             const std::string& ownTerm, const std::string& storageName) :
         ArMemError(makeMsg(expectedName, ownTerm, storageName))
@@ -59,6 +80,22 @@ namespace armarx::armem::error
 
 
 
+    MissingData::MissingData(const std::string& missingTerm, const std::string& missingName,
+                             const std::string& ownTerm, const std::string& ownName) :
+        ArMemError(makeMsg(missingTerm, missingName, ownTerm, ownName))
+    {
+    }
+
+    std::string MissingData::makeMsg(const std::string& missingTerm, const std::string& missingName,
+                                     const std::string& ownTerm, const std::string& ownName)
+    {
+        std::stringstream ss;
+        ss << "No " << missingTerm << " data at '" << missingName << "' "
+           << "in " << ownTerm << " '" << ownName << "'.";
+        return ss.str();
+    }
+
+
     ParseIntegerError::ParseIntegerError(std::string string, std::string semanticName) :
         ArMemError(makeMsg(string, semanticName))
     {
@@ -121,4 +158,5 @@ namespace armarx::armem::error
         return ss.str();
     }
 
+
 }
diff --git a/source/RobotAPI/libraries/armem/error/ArMemError.h b/source/RobotAPI/libraries/armem/error/ArMemError.h
index 5dd1a9118fb11a1b66405d15fd41b544955c2bdb..a85d26ce5000e7780208f2d7b1ae3afa75f9fad4 100644
--- a/source/RobotAPI/libraries/armem/error/ArMemError.h
+++ b/source/RobotAPI/libraries/armem/error/ArMemError.h
@@ -21,6 +21,23 @@ namespace armarx::armem::error
     };
 
 
+    /**
+     * @brief Indicates that an argument was invalid.
+     */
+    class InvalidArgument : public ArMemError
+    {
+    public:
+
+        InvalidArgument(const std::string& argument, const std::string& function,
+                        const std::string& message);
+
+        static std::string makeMsg(const std::string& argument, const std::string& function,
+                                   const std::string& message);
+
+    };
+
+
+
     /**
      * @brief Indicates that a name in a given ID does not match a storage's own name.
      */
@@ -68,7 +85,22 @@ namespace armarx::armem::error
 
 
     /**
-     * @brief Indicates that a storage did not have an entry under a given name.
+     * @brief Indicates that a container did have an entry, but the entry's data was
+     * null when trying to access it.
+     */
+    class MissingData : public ArMemError
+    {
+    public:
+        MissingData(const std::string& missingTerm, const std::string& missingName,
+                    const std::string& ownTerm, const std::string& ownName);
+
+        static std::string makeMsg(const std::string& missingTerm, const std::string& missingName,
+                                   const std::string& ownTerm, const std::string& ownName);
+    };
+
+
+    /**
+     * @brief Indicates that a string could not be parsed as integer.
      */
     class ParseIntegerError : public ArMemError
     {
diff --git a/source/RobotAPI/libraries/armem/memory/Entity.cpp b/source/RobotAPI/libraries/armem/memory/Entity.cpp
index 4c56024a850bc1d38063a6061e2749c7001f1d29..2e563ee2e553bfce514a030ae18b55c359e48974 100644
--- a/source/RobotAPI/libraries/armem/memory/Entity.cpp
+++ b/source/RobotAPI/libraries/armem/memory/Entity.cpp
@@ -50,6 +50,12 @@ namespace armarx::armem
         return history.count(time) > 0;
     }
 
+    bool Entity::hasSnapshotData(Time time) const
+    {
+        auto it = history.find(time);
+        return it != history.end() && (it->second != nullptr);
+    }
+
     EntitySnapshot& Entity::getSnapshot(Time time)
     {
         return const_cast<EntitySnapshot&>(const_cast<const Entity*>(this)->getSnapshot(time));
@@ -60,8 +66,15 @@ namespace armarx::armem
         auto it = history.find(time);
         if (it != history.end())
         {
-            ARMARX_CHECK_NOT_NULL(it->second);
-            return *it->second;
+            if (it->second)
+            {
+                return *it->second;
+            }
+            else
+            {
+                throw error::MissingData("entity snapshot", toDateTimeMilliSeconds(time),
+                                         getLevelName(), this->name);
+            }
         }
         else
         {
@@ -89,8 +102,15 @@ namespace armarx::armem
     const EntitySnapshot& Entity::getLatestSnapshot() const
     {
         auto& latest = getLatestItem();
-        ARMARX_CHECK_NOT_NULL(latest.second);
-        return *latest.second;
+        if (latest.second)
+        {
+            return *latest.second;
+        }
+        else
+        {
+            throw error::MissingData("entity snapshot", toDateTimeMilliSeconds(latest.first),
+                                     getLevelName(), this->name);
+        }
     }
 
     Time Entity::getLatestTimestamp() const
@@ -111,6 +131,10 @@ namespace armarx::armem
 
     EntitySnapshot& Entity::addSnapshot(EntitySnapshotPtr&& snapshot)
     {
+        if (!snapshot)
+        {
+            throw error::InvalidArgument("snapshot", __FUNCTION__, "Passed snapshot pointer is null.");
+        }
         auto it = history.emplace(snapshot->time, std::move(snapshot)).first;
         return *it->second;
     }
@@ -140,6 +164,12 @@ namespace armarx::armem
     }
 
 
+    EntitySnapshotPtr& Entity::addSnapshotEntry(Time time)
+    {
+        return history.emplace(time, nullptr).first->second;
+    }
+
+
     void Entity::setMaxHistorySize(long maxSize)
     {
         this->maxHistorySize = maxSize;
diff --git a/source/RobotAPI/libraries/armem/memory/Entity.h b/source/RobotAPI/libraries/armem/memory/Entity.h
index 742b6709f3f1f7293e76f1f0bb847224f995af68..a03400cb9881b228f906612cb271abdeebb75511 100644
--- a/source/RobotAPI/libraries/armem/memory/Entity.h
+++ b/source/RobotAPI/libraries/armem/memory/Entity.h
@@ -33,8 +33,36 @@ namespace armarx::armem
         Entity& operator=(const Entity& other);
 
 
+        /**
+         * @brief Indicates whether a history entry for the given time exists.
+         */
         bool hasSnapshot(Time time) const;
+        /**
+         * @brief Indicates whether a history entry for the given time exists
+         * and its data is not null.
+         */
+        bool hasSnapshotData(Time time) const;
+
+
+        /**
+         * @brief Get the latest timestamp.
+         * @throw `armem::error::EntityHistoryEmpty` If the history is empty.
+         */
+        Time getLatestTimestamp() const;
+        /**
+         * @brief Get all timestamps in the history.
+         */
+        std::vector<Time> getTimestamps() const;
+
 
+        /**
+         * @brief Get a snapshot.
+         * @param time The time.
+         * @return The snapshot, if it exists.
+         *
+         * @throws `armem::error::MissingEntry` If there is no such entry.
+         * @throws `armem::error::MissingData` If the entry has no data.
+         */
         EntitySnapshot& getSnapshot(Time time);
         const EntitySnapshot& getSnapshot(Time time) const;
 
@@ -45,21 +73,11 @@ namespace armarx::armem
          * @brief Return the snapshot with the most recent timestamp.
          * @return The latest snapshot.
          * @throw `armem::error::EntityHistoryEmpty` If the history is empty.
+         * @throw `armem::error::MissingData` If the latest snapshot has no data.
          */
         EntitySnapshot& getLatestSnapshot();
         const EntitySnapshot& getLatestSnapshot() const;
 
-        /**
-         * @brief Get the latest timestamp.
-         * @throw `armem::error::EntityHistoryEmpty` If the history is empty.
-         */
-        Time getLatestTimestamp() const;
-
-        /**
-         * @brief Get all timestamps in the history.
-         */
-        std::vector<Time> getTimestamps() const;
-
 
         /**
          * @brief Add the given update to this entity's history.
@@ -68,10 +86,22 @@ namespace armarx::armem
          */
         MemoryID update(const InternalEntityUpdate& update);
 
-        /// Add a single snapshot.
+        /**
+         * @brief Add a single snapshot entry without data.
+         * @param time The time.
+         * @return The (empty) snapshot pointer.
+         */
+        EntitySnapshotPtr& addSnapshotEntry(Time time);
+
+        /**
+         * @brief Add a single snapshot with data.
+         * @param snapshot The snapshot.
+         * @return The stored snapshot.
+         */
         EntitySnapshot& addSnapshot(const EntitySnapshot& snapshot);
         EntitySnapshot& addSnapshot(EntitySnapshotPtr&& snapshot);
 
+
         /// Get a cleared copy of `*this` (with empty history).
         EntityPtr getEmptyCopy() const;