diff --git a/include/libcamera/internal/value_node.h b/include/libcamera/internal/value_node.h
index f8d0329f7670..3bdb537e9eab 100644
--- a/include/libcamera/internal/value_node.h
+++ b/include/libcamera/internal/value_node.h
@@ -143,17 +143,31 @@ public:
 		}
 	};
 
-	class DictAdapter : public Adapter<DictIterator<const ValueNode,
-							ValueContainer::const_iterator>,
-					   const ValueContainer>
+	class DictAdapter : public Adapter<DictIterator<ValueNode,
+							ValueContainer::iterator>,
+					   ValueContainer>
 	{
 	public:
 		using key_type = std::string;
 	};
 
-	class ListAdapter : public Adapter<ListIterator<const ValueNode,
-							ValueContainer::const_iterator>,
-					   const ValueContainer>
+	class ListAdapter : public Adapter<ListIterator<ValueNode,
+							ValueContainer::iterator>,
+					   ValueContainer>
+	{
+	};
+
+	class ConstDictAdapter : public Adapter<DictIterator<const ValueNode,
+							     ValueContainer::const_iterator>,
+						const ValueContainer>
+	{
+	public:
+		using key_type = std::string;
+	};
+
+	class ConstListAdapter : public Adapter<ListIterator<const ValueNode,
+							     ValueContainer::const_iterator>,
+						const ValueContainer>
 	{
 	};
 #endif /* __DOXYGEN__ */
@@ -211,8 +225,10 @@ public:
 			.set(*this, std::forward<T>(value));
 	}
 
-	DictAdapter asDict() const { return DictAdapter{ list_ }; }
-	ListAdapter asList() const { return ListAdapter{ list_ }; }
+	DictAdapter asDict() { return DictAdapter{ list_ }; }
+	ListAdapter asList() { return ListAdapter{ list_ }; }
+	ConstDictAdapter asDict() const { return ConstDictAdapter{ list_ }; }
+	ConstListAdapter asList() const { return ConstListAdapter{ list_ }; }
 
 	const ValueNode &operator[](std::size_t index) const;
 
diff --git a/src/libcamera/value_node.cpp b/src/libcamera/value_node.cpp
index 6c9e2239165b..5aef72cd29a4 100644
--- a/src/libcamera/value_node.cpp
+++ b/src/libcamera/value_node.cpp
@@ -335,6 +335,11 @@ template struct ValueNode::Accessor<std::vector<uint32_t>>;
 template struct ValueNode::Accessor<std::vector<std::string>>;
 #endif /* __DOXYGEN__ */
 
+/**
+ * \fn ValueNode::asDict()
+ * \copydoc ValueNode::asDict() const
+ */
+
 /**
  * \fn ValueNode::asDict() const
  * \brief Wrap a dictionary ValueNode in an adapter that exposes iterators
@@ -355,6 +360,11 @@ template struct ValueNode::Accessor<std::vector<std::string>>;
  * \return An adapter of unspecified type compatible with range-based for loops
  */
 
+/**
+ * \fn ValueNode::asList()
+ * \copydoc ValueNode::asList() const
+ */
+
 /**
  * \fn ValueNode::asList() const
  * \brief Wrap a list ValueNode in an adapter that exposes iterators
