diff --git a/Makefile b/Makefile
index 29f9bd7c39f4b7541c0056b6cc3a8636891daa04..9c8fb41f709defcd56d8f7730f801de9a873c640 100644
--- a/Makefile
+++ b/Makefile
@@ -80,6 +80,7 @@ conan: conan-install-deps conan-create
 .PHONY: conan
 
 doc:
+	@doxygen --version || ( echo "Doxygen not found.  Please install Doxygen first." ; exit 1 )
 	mkdir -p build && cd build && conan install .. --build=missing -s $(CONAN_SETTINGS) \
 	  && cmake .. && cmake --build . --target doc-sphinx \
 	  && echo "The documentation starts at build/doc/sphinx_out/index.html ."
diff --git a/doc/CHANGELOG.md b/doc/CHANGELOG.md
index 66d8b3660215477bf3e0ba83b7f115d7637352fe..7d0a100c879a2a87b6738c766e2882da96d5af14 100644
--- a/doc/CHANGELOG.md
+++ b/doc/CHANGELOG.md
@@ -22,6 +22,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Fixed
 
+- Values can now hold empty vectors and do not silently convert them into a scalar.
+
 ### Security
 
 ### Documentation
diff --git a/doc/Install_develop.rst b/doc/Install_develop.rst
index 9704ada8e982dd7881a220433cce101c4f4def97..5aa5c8a6c9af7d33a2b11f54af60f7c9c5bd8fa2 100644
--- a/doc/Install_develop.rst
+++ b/doc/Install_develop.rst
@@ -189,11 +189,14 @@ test``. If you want to build manually, follow these steps:
     - Depending on the clang version it may be necessary to also add
       ``-DCMAKE_CXX_FLAGS="-Wno-unused-parameter"``
 4. ``cmake --build .``
+    - If this fails with ``Error running '': No such file or directory``, you may want to try
+      CMake's ``-D SKIP_LINTING=ON``. (See previous step.)
 
 Run
 ^^^
 
-In the build directory, run ``ctest``
+In the build directory, run ``ctest``.  For more verbose output of a single test:
+``ctest -R test_value.test_list -V``
 
 Framework
 ^^^^^^^^^
diff --git a/include/caosdb/value.h b/include/caosdb/value.h
index cffb11162b9ed8b83508316c155f1fca46be2714..1da6f1c2178b1b9091b990a016e1959b5e7f2a4c 100644
--- a/include/caosdb/value.h
+++ b/include/caosdb/value.h
@@ -36,6 +36,10 @@
     for (const auto &value : values) {                                                             \
       this->wrapped->mutable_list_values()->add_values()->SETTER(value);                           \
     }                                                                                              \
+    if (values.empty()) {                                                                          \
+      this->wrapped->mutable_list_values()->add_values()->set_special_value(                       \
+        ProtoSpecialValue::SPECIAL_VALUE_UNSPECIFIED);                                             \
+    }                                                                                              \
   }
 
 namespace caosdb::entity {
@@ -385,7 +389,9 @@ public:
     return !IsNull() && this->wrapped->value_case() == ValueCase::kListValues;
   }
   [[nodiscard]] inline auto GetAsVector() const noexcept -> const std::vector<ScalarValue> & {
-    if (!IsVector()) {
+    if (!IsVector() || (this->wrapped->list_values().values(0).has_special_value() &&
+                        this->wrapped->list_values().values(0).special_value() ==
+                          ProtoSpecialValue::SPECIAL_VALUE_UNSPECIFIED)) {
       // create empty list
       static std::vector<ScalarValue> empty_values;
       return empty_values;
diff --git a/test/test_value.cpp b/test/test_value.cpp
index 1d959acf40c766c2123b7fdc541b642126983fcc..767965df68e648a04ba64a4148dc58839ebcc08c 100644
--- a/test/test_value.cpp
+++ b/test/test_value.cpp
@@ -137,6 +137,14 @@ TEST(test_value, test_list) {
     EXPECT_EQ(item.IsString(), true);
     EXPECT_EQ(item.GetAsString(), "id" + std::to_string(counter++));
   }
+
+  // Test empty lists
+  auto empty_content = std::vector<int>();
+  Value value_0(empty_content);
+  EXPECT_TRUE(value_0.IsVector());
+  auto const &list_value_0 = value_0.GetAsVector();
+  EXPECT_EQ(list_value_0.size(), 0);
+  EXPECT_TRUE(list_value_0.empty());
 }
 
 TEST(test_value, test_scalar_value_to_value) {