diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp
index b161bc6b3ed6..6b58dd554873 100644
--- a/src/android/camera_capabilities.cpp
+++ b/src/android/camera_capabilities.cpp
@@ -17,6 +17,7 @@
 #include <hardware/camera3.h>
 
 #include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
 
 #include <libcamera/control_ids.h>
 #include <libcamera/controls.h>
@@ -1064,7 +1065,7 @@ int CameraCapabilities::initializeStaticMetadata()
 	/* Sensor static metadata. */
 	std::array<int32_t, 2> pixelArraySize;
 	{
-		const Size &size = properties.get(properties::PixelArraySize).value_or(Size{});
+		const Size &size = properties.get(properties::PixelArraySize).value_or(utils::defopt);
 		pixelArraySize[0] = size.width;
 		pixelArraySize[1] = size.height;
 		staticMetadata_->addEntry(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
@@ -1083,7 +1084,7 @@ int CameraCapabilities::initializeStaticMetadata()
 
 	{
 		const Span<const Rectangle> rects =
-			properties.get(properties::PixelArrayActiveAreas).value_or(Span<const Rectangle>{});
+			properties.get(properties::PixelArrayActiveAreas).value_or(utils::defopt);
 		std::vector<int32_t> data{
 			static_cast<int32_t>(rects[0].x),
 			static_cast<int32_t>(rects[0].y),
diff --git a/src/ipa/libipa/agc_mean_luminance.cpp b/src/ipa/libipa/agc_mean_luminance.cpp
index 1d385551adc6..c226dd23552c 100644
--- a/src/ipa/libipa/agc_mean_luminance.cpp
+++ b/src/ipa/libipa/agc_mean_luminance.cpp
@@ -11,6 +11,8 @@
 #include <cmath>
 
 #include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
+
 #include <libcamera/control_ids.h>
 
 #include "exposure_mode_helper.h"
@@ -288,9 +290,9 @@ int AgcMeanLuminance::parseExposureModes(const ValueNode &tuningData)
 			}
 
 			std::vector<uint32_t> exposureTimes =
-				modeValues["exposureTime"].get<std::vector<uint32_t>>().value_or(std::vector<uint32_t>{});
+				modeValues["exposureTime"].get<std::vector<uint32_t>>().value_or(utils::defopt);
 			std::vector<double> gains =
-				modeValues["gain"].get<std::vector<double>>().value_or(std::vector<double>{});
+				modeValues["gain"].get<std::vector<double>>().value_or(utils::defopt);
 
 			if (exposureTimes.size() != gains.size()) {
 				LOG(AgcMeanLuminance, Error)
diff --git a/src/ipa/libipa/awb_bayes.cpp b/src/ipa/libipa/awb_bayes.cpp
index a1412c8bd2b5..9fd85e5a4505 100644
--- a/src/ipa/libipa/awb_bayes.cpp
+++ b/src/ipa/libipa/awb_bayes.cpp
@@ -16,6 +16,8 @@
 #include <vector>
 
 #include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
+
 #include <libcamera/control_ids.h>
 
 #include "colours.h"
@@ -211,9 +213,9 @@ int AwbBayes::readPriors(const ValueNode &tuningData)
 		}
 
 		std::vector<uint32_t> temperatures =
-			p["ct"].get<std::vector<uint32_t>>().value_or(std::vector<uint32_t>{});
+			p["ct"].get<std::vector<uint32_t>>().value_or(utils::defopt);
 		std::vector<double> probabilities =
-			p["probability"].get<std::vector<double>>().value_or(std::vector<double>{});
+			p["probability"].get<std::vector<double>>().value_or(utils::defopt);
 
 		if (temperatures.size() != probabilities.size()) {
 			LOG(Awb, Error)
diff --git a/src/ipa/mali-c55/algorithms/lsc.cpp b/src/ipa/mali-c55/algorithms/lsc.cpp
index fe230fdff418..36e50163aecc 100644
--- a/src/ipa/mali-c55/algorithms/lsc.cpp
+++ b/src/ipa/mali-c55/algorithms/lsc.cpp
@@ -7,6 +7,8 @@
 
 #include "lsc.h"
 
+#include <libcamera/base/utils.h>
+
 #include "libcamera/internal/value_node.h"
 
 namespace libcamera {
@@ -48,11 +50,11 @@ int Lsc::init([[maybe_unused]] IPAContext &context, const ValueNode &tuningData)
 		}
 
 		std::vector<uint8_t> rTable =
-			yamlSet["r"].get<std::vector<uint8_t>>().value_or(std::vector<uint8_t>{});
+			yamlSet["r"].get<std::vector<uint8_t>>().value_or(utils::defopt);
 		std::vector<uint8_t> gTable =
-			yamlSet["g"].get<std::vector<uint8_t>>().value_or(std::vector<uint8_t>{});
+			yamlSet["g"].get<std::vector<uint8_t>>().value_or(utils::defopt);
 		std::vector<uint8_t> bTable =
-			yamlSet["b"].get<std::vector<uint8_t>>().value_or(std::vector<uint8_t>{});
+			yamlSet["b"].get<std::vector<uint8_t>>().value_or(utils::defopt);
 
 		/*
 		 * Some validation to do; only 16x16 and 32x32 tables of
diff --git a/src/ipa/rkisp1/algorithms/agc.cpp b/src/ipa/rkisp1/algorithms/agc.cpp
index 523930488a3b..9bb9d943163f 100644
--- a/src/ipa/rkisp1/algorithms/agc.cpp
+++ b/src/ipa/rkisp1/algorithms/agc.cpp
@@ -55,7 +55,7 @@ int Agc::parseMeteringModes(IPAContext &context, const ValueNode &tuningData)
 		}
 
 		std::vector<uint8_t> weights =
-			value.get<std::vector<uint8_t>>().value_or(std::vector<uint8_t>{});
+			value.get<std::vector<uint8_t>>().value_or(utils::defopt);
 		if (weights.size() != context.hw.numHistogramWeights) {
 			LOG(RkISP1Agc, Warning)
 				<< "Failed to read metering mode'" << key << "'";
diff --git a/src/ipa/rkisp1/algorithms/dpf.cpp b/src/ipa/rkisp1/algorithms/dpf.cpp
index 5c5b539f1ee8..b2c9ec568b97 100644
--- a/src/ipa/rkisp1/algorithms/dpf.cpp
+++ b/src/ipa/rkisp1/algorithms/dpf.cpp
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
 
 #include <libcamera/control_ids.h>
 
@@ -72,7 +73,7 @@ int Dpf::init([[maybe_unused]] IPAContext &context,
 	 *    +---------|--------> X
 	 *     -4....-1 0 1 2 3 4
 	 */
-	values = dFObject["g"].get<std::vector<uint8_t>>().value_or(std::vector<uint8_t>{});
+	values = dFObject["g"].get<std::vector<uint8_t>>().value_or(utils::defopt);
 	if (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS) {
 		LOG(RkISP1Dpf, Error)
 			<< "Invalid 'DomainFilter:g': expected "
@@ -108,7 +109,7 @@ int Dpf::init([[maybe_unused]] IPAContext &context,
 	 * For a 9x9 kernel, columns -6 and 6 are dropped, so coefficient
 	 * number 6 is not used.
 	 */
-	values = dFObject["rb"].get<std::vector<uint8_t>>().value_or(std::vector<uint8_t>{});
+	values = dFObject["rb"].get<std::vector<uint8_t>>().value_or(utils::defopt);
 	if (values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS &&
 	    values.size() != RKISP1_CIF_ISP_DPF_MAX_SPATIAL_COEFFS - 1) {
 		LOG(RkISP1Dpf, Error)
@@ -137,7 +138,7 @@ int Dpf::init([[maybe_unused]] IPAContext &context,
 	const ValueNode &rFObject = tuningData["NoiseLevelFunction"];
 
 	std::vector<uint16_t> nllValues;
-	nllValues = rFObject["coeff"].get<std::vector<uint16_t>>().value_or(std::vector<uint16_t>{});
+	nllValues = rFObject["coeff"].get<std::vector<uint16_t>>().value_or(utils::defopt);
 	if (nllValues.size() != RKISP1_CIF_ISP_DPF_MAX_NLF_COEFFS) {
 		LOG(RkISP1Dpf, Error)
 			<< "Invalid 'RangeFilter:coeff': expected "
diff --git a/src/ipa/rkisp1/algorithms/gsl.cpp b/src/ipa/rkisp1/algorithms/gsl.cpp
index d6272f3a39ef..d83aab8506f3 100644
--- a/src/ipa/rkisp1/algorithms/gsl.cpp
+++ b/src/ipa/rkisp1/algorithms/gsl.cpp
@@ -59,7 +59,7 @@ int GammaSensorLinearization::init([[maybe_unused]] IPAContext &context,
 				   const ValueNode &tuningData)
 {
 	std::vector<uint16_t> xIntervals =
-		tuningData["x-intervals"].get<std::vector<uint16_t>>().value_or(std::vector<uint16_t>{});
+		tuningData["x-intervals"].get<std::vector<uint16_t>>().value_or(utils::defopt);
 	if (xIntervals.size() != kDegammaXIntervals) {
 		LOG(RkISP1Gsl, Error)
 			<< "Invalid 'x' coordinates: expected "
@@ -83,7 +83,7 @@ int GammaSensorLinearization::init([[maybe_unused]] IPAContext &context,
 		return -EINVAL;
 	}
 
-	curveYr_ = yObject["red"].get<std::vector<uint16_t>>().value_or(std::vector<uint16_t>{});
+	curveYr_ = yObject["red"].get<std::vector<uint16_t>>().value_or(utils::defopt);
 	if (curveYr_.size() != RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE) {
 		LOG(RkISP1Gsl, Error)
 			<< "Invalid 'y:red' coordinates: expected "
@@ -92,7 +92,7 @@ int GammaSensorLinearization::init([[maybe_unused]] IPAContext &context,
 		return -EINVAL;
 	}
 
-	curveYg_ = yObject["green"].get<std::vector<uint16_t>>().value_or(std::vector<uint16_t>{});
+	curveYg_ = yObject["green"].get<std::vector<uint16_t>>().value_or(utils::defopt);
 	if (curveYg_.size() != RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE) {
 		LOG(RkISP1Gsl, Error)
 			<< "Invalid 'y:green' coordinates: expected "
@@ -101,7 +101,7 @@ int GammaSensorLinearization::init([[maybe_unused]] IPAContext &context,
 		return -EINVAL;
 	}
 
-	curveYb_ = yObject["blue"].get<std::vector<uint16_t>>().value_or(std::vector<uint16_t>{});
+	curveYb_ = yObject["blue"].get<std::vector<uint16_t>>().value_or(utils::defopt);
 	if (curveYb_.size() != RKISP1_CIF_ISP_DEGAMMA_CURVE_SIZE) {
 		LOG(RkISP1Gsl, Error)
 			<< "Invalid 'y:blue' coordinates: expected "
diff --git a/src/ipa/rkisp1/algorithms/lsc.cpp b/src/ipa/rkisp1/algorithms/lsc.cpp
index 54e374bd9c3c..25f7c512b35c 100644
--- a/src/ipa/rkisp1/algorithms/lsc.cpp
+++ b/src/ipa/rkisp1/algorithms/lsc.cpp
@@ -317,7 +317,7 @@ std::vector<uint16_t> LscTableLoader::parseTable(const ValueNode &tuningData,
 		RKISP1_CIF_ISP_LSC_SAMPLES_MAX * RKISP1_CIF_ISP_LSC_SAMPLES_MAX;
 
 	std::vector<uint16_t> table =
-		tuningData[prop].get<std::vector<uint16_t>>().value_or(std::vector<uint16_t>{});
+		tuningData[prop].get<std::vector<uint16_t>>().value_or(utils::defopt);
 	if (table.size() != kLscNumSamples) {
 		LOG(RkISP1Lsc, Error)
 			<< "Invalid '" << prop << "' values: expected "
@@ -333,7 +333,7 @@ std::vector<double> parseSizes(const ValueNode &tuningData,
 			       const char *prop)
 {
 	std::vector<double> sizes =
-		tuningData[prop].get<std::vector<double>>().value_or(std::vector<double>{});
+		tuningData[prop].get<std::vector<double>>().value_or(utils::defopt);
 	if (sizes.size() != RKISP1_CIF_ISP_LSC_SECTORS_TBL_SIZE) {
 		LOG(RkISP1Lsc, Error)
 			<< "Invalid '" << prop << "' values: expected "
diff --git a/src/libcamera/ipa_manager.cpp b/src/libcamera/ipa_manager.cpp
index a351f4f7b581..41918e4c2934 100644
--- a/src/libcamera/ipa_manager.cpp
+++ b/src/libcamera/ipa_manager.cpp
@@ -123,7 +123,7 @@ IPAManager::IPAManager(const CameraManager &cm)
 	/* User-specified paths take precedence. */
 	const auto modulePaths =
 		configuration.listOption({ "ipa", "module_paths" })
-			.value_or(std::vector<std::string>());
+			.value_or(utils::defopt);
 	for (const auto &dir : modulePaths) {
 		if (dir.empty())
 			continue;
diff --git a/src/libcamera/ipa_proxy.cpp b/src/libcamera/ipa_proxy.cpp
index bc8ff090fa86..83efe1dc6368 100644
--- a/src/libcamera/ipa_proxy.cpp
+++ b/src/libcamera/ipa_proxy.cpp
@@ -125,9 +125,9 @@ IPAProxy::IPAProxy(IPAModule *ipam, const CameraManager &cm)
 	const GlobalConfiguration &configuration = cm._d()->configuration();
 
 	configPaths_ = configuration.listOption({ "ipa", "config_paths" })
-				    .value_or(std::vector<std::string>());
+				    .value_or(utils::defopt);
 	execPaths_ = configuration.listOption({ "ipa", "proxy_paths" })
-				  .value_or(std::vector<std::string>());
+				  .value_or(utils::defopt);
 }
 
 IPAProxy::~IPAProxy()
diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
index c7799f2b4bd9..cc7e32c32337 100644
--- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp
+++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp
@@ -2190,7 +2190,7 @@ int PiSPCameraData::configureEntities(V4L2SubdeviceFormat sensorFormat,
 	};
 	const V4L2Subdevice::Stream embeddedDataStream{
 		csiVideoSinkPad,
-		sensor_->embeddedDataStream().value_or(V4L2Subdevice::Stream{}).stream
+		sensor_->embeddedDataStream().value_or(utils::defopt).stream
 	};
 
 	V4L2Subdevice::Routing routing;
diff --git a/src/v4l2/v4l2_compat_manager.cpp b/src/v4l2/v4l2_compat_manager.cpp
index a92f2e2944fc..1a0ba5fef3ca 100644
--- a/src/v4l2/v4l2_compat_manager.cpp
+++ b/src/v4l2/v4l2_compat_manager.cpp
@@ -117,7 +117,7 @@ int V4L2CompatManager::getCameraIndex(int fd)
 	for (auto [index, camera] : utils::enumerate(cameras)) {
 		Span<const int64_t> devices = camera->properties()
 						      .get(properties::SystemDevices)
-						      .value_or(Span<int64_t>{});
+						      .value_or(utils::defopt);
 
 		/*
 		 * While there may be multiple cameras that could reference the
diff --git a/test/value-node.cpp b/test/value-node.cpp
index 3b6466e75b13..a6977d5429c8 100644
--- a/test/value-node.cpp
+++ b/test/value-node.cpp
@@ -509,7 +509,7 @@ protected:
 				},
 
 				[&](const Size &arg) -> int {
-					if (node.get<Size>().value_or(Size{}) != arg ||
+					if (node.get<Size>().value_or(utils::defopt) != arg ||
 					    node.get<Size>(Size{}) != arg) {
 						std::cerr
 							<< "Invalid node size value"
@@ -521,7 +521,7 @@ protected:
 				},
 
 				[&](const std::string &arg) -> int {
-					if (node.get<std::string>().value_or(std::string{}) != arg ||
+					if (node.get<std::string>().value_or(utils::defopt) != arg ||
 					    node.get<std::string>(std::string{}) != arg) {
 						std::cerr
 							<< "Invalid node string value"
