diff --git a/SDK/C++/private/operator_impl.cpp b/SDK/C++/private/operator_impl.cpp
index a3e65a759388f01523a1d33c179bcd12bdbff802..41f376c209d9d8ba7b5bfbd1c05a155890355643 100644
--- a/SDK/C++/private/operator_impl.cpp
+++ b/SDK/C++/private/operator_impl.cpp
@@ -17,5 +17,6 @@ OperatorImpl::~OperatorImpl()
 
 voltu::PropertyPtr OperatorImpl::property(const std::string &name)
 {
+	if (!cfg_->has(name)) throw voltu::exceptions::BadPropertyName();
 	return std::make_shared<voltu::internal::CfgPropertyImpl>(cfg_, name);
 }
diff --git a/components/common/cpp/include/ftl/configurable.hpp b/components/common/cpp/include/ftl/configurable.hpp
index dadba17b4c19b7d1e2ce8de103b4e8f6cb22ad9f..3d2a115e670e977fc45e4b8fdb32ff055789dd6c 100644
--- a/components/common/cpp/include/ftl/configurable.hpp
+++ b/components/common/cpp/include/ftl/configurable.hpp
@@ -70,6 +70,8 @@ class Configurable {
 	template <typename T>
 	inline bool is(const std::string &name) { return false; }
 
+	bool has(const std::string &name) const;
+
 	/**
 	 * Get a configuration property, but return a default if not found.
 	 */
diff --git a/components/common/cpp/src/configurable.cpp b/components/common/cpp/src/configurable.cpp
index 4f6bff5bac5cf66ca46af9c36c17aaaf43c074dc..c5f6d9d868806dbe3dc87f64f1069d887bf26b01 100644
--- a/components/common/cpp/src/configurable.cpp
+++ b/components/common/cpp/src/configurable.cpp
@@ -151,6 +151,10 @@ bool ftl::Configurable::is<double>(const std::string &name) {
 	return getConfig()[name].is_number_float();
 }
 
+bool ftl::Configurable::has(const std::string &name) const {
+	return (config_) ? config_->contains(name) : false;
+}
+
 void Configurable::required(const char *f, const std::vector<std::tuple<std::string, std::string, std::string>> &r) {
 	bool diderror = false;
 	for (auto i : r) {