Skip to content

Commit 7066303

Browse files
committed
fix: fix uncaught exception on some error formats
1 parent 6288cb8 commit 7066303

File tree

1 file changed

+58
-33
lines changed

1 file changed

+58
-33
lines changed

src/dpp/cluster/confirmation.cpp

+58-33
Original file line numberDiff line numberDiff line change
@@ -74,22 +74,31 @@ bool confirmation_callback_t::is_error() const {
7474

7575
namespace {
7676

77-
std::vector<error_detail> find_errors_in_array(const std::string& obj, size_t index, const std::string& current_field, json::iterator begin, json::iterator end) {
77+
std::vector<error_detail> find_errors_in_array(const std::string& obj, int index, const std::string& current_field, const json &j);
78+
79+
std::vector<error_detail> find_errors_in_object(const std::string& obj, int index, const std::string& current_field, const json &j) {
7880
std::vector<error_detail> ret;
7981

80-
for (auto it = begin; it != end; ++it) {
81-
if (auto errors = it->find("_errors"); errors != it->end()) {
82-
for (auto errordetails = errors->begin(); errordetails != errors->end(); ++errordetails) {
83-
error_detail detail;
84-
detail.code = (*errordetails)["code"].get<std::string>();
85-
detail.reason = (*errordetails)["message"].get<std::string>();
86-
detail.field = current_field + it.key();
87-
detail.object = obj;
88-
detail.index = index;
89-
ret.emplace_back(detail);
82+
if (auto errors = j.find("_errors"); errors != j.end()) {
83+
for (auto errordetails = errors->begin(); errordetails != errors->end(); ++errordetails) {
84+
error_detail detail;
85+
detail.code = (*errordetails)["code"].get<std::string>();
86+
detail.reason = (*errordetails)["message"].get<std::string>();
87+
detail.field = current_field;
88+
detail.object = obj;
89+
detail.index = index;
90+
ret.emplace_back(detail);
91+
}
92+
} else {
93+
for (auto it = j.begin(); it != j.end(); ++it) {
94+
std::vector<error_detail> sub_errors;
95+
std::string field = obj.empty() ? current_field : obj + '.' + current_field;
96+
97+
if (it->is_array()) {
98+
sub_errors = find_errors_in_array(field, index, it.key(), *it);
99+
} else {
100+
sub_errors = find_errors_in_object(field, index, it.key(), *it);
90101
}
91-
} else { // subobject has errors
92-
auto sub_errors = find_errors_in_array(obj, index, current_field + it.key() + ".", it->begin(), it->end());
93102

94103
if (!sub_errors.empty()) {
95104
ret.reserve(ret.capacity() + sub_errors.size());
@@ -100,6 +109,30 @@ std::vector<error_detail> find_errors_in_array(const std::string& obj, size_t in
100109
return ret;
101110
}
102111

112+
std::vector<error_detail> find_errors_in_array(const std::string& obj, int index, const std::string& current_field, const json &j) {
113+
std::vector<error_detail> ret;
114+
int idx = 0;
115+
116+
for (auto it = j.begin(); it != j.end(); ++it) {
117+
std::vector<error_detail> sub_errors;
118+
std::string key = '[' + std::to_string(idx) + ']';
119+
std::string field = obj.empty() ? current_field : obj + '.' + current_field;
120+
121+
if (it->is_array()) {
122+
sub_errors = find_errors_in_array(field, index, key, *it);
123+
} else {
124+
sub_errors = find_errors_in_object(field, index, key, *it);
125+
}
126+
127+
if (!sub_errors.empty()) {
128+
ret.reserve(ret.capacity() + sub_errors.size());
129+
std::move(sub_errors.begin(), sub_errors.end(), std::back_inserter(ret));
130+
}
131+
++idx;
132+
}
133+
return ret;
134+
}
135+
103136
}
104137

105138
error_info confirmation_callback_t::get_error() const {
@@ -158,29 +191,18 @@ error_info confirmation_callback_t::get_error() const {
158191
}
159192
}
160193
}
194+
} else {
195+
std::vector<error_detail> sub_errors;
161196

162-
} else if (obj->find("_errors") != obj->end()) {
163-
/* An object of error messages (rare) */
164-
e.errors.reserve((*obj)["_errors"].size());
165-
for (auto errordetails = (*obj)["_errors"].begin(); errordetails != (*obj)["_errors"].end(); ++errordetails) {
166-
error_detail detail;
167-
detail.code = (*errordetails)["code"].get<std::string>();
168-
detail.reason = (*errordetails)["message"].get<std::string>();
169-
detail.object.clear();
170-
detail.field = obj.key();
171-
detail.index = 0;
172-
e.errors.emplace_back(detail);
197+
if (obj->is_array()) {
198+
sub_errors = find_errors_in_array({}, -1, obj.key(), *obj);
199+
} else {
200+
sub_errors = find_errors_in_object({}, -1, obj.key(), *obj);
173201
}
174-
} else {
175-
/* An object that has a subobject with errors */
176-
for (auto index = obj->begin(); index != obj->end(); ++index) {
177-
int array_index = std::atoll(index.key().c_str());
178-
auto sub_errors = find_errors_in_array(obj.key(), array_index, {}, index->begin(), index->end());
179202

180-
if (!sub_errors.empty()) {
181-
e.errors.reserve(e.errors.capacity() + sub_errors.size());
182-
std::move(sub_errors.begin(), sub_errors.end(), std::back_inserter(e.errors));
183-
}
203+
if (!sub_errors.empty()) {
204+
e.errors.reserve(e.errors.capacity() + sub_errors.size());
205+
std::move(sub_errors.begin(), sub_errors.end(), std::back_inserter(e.errors));
184206
}
185207
}
186208
}
@@ -194,6 +216,9 @@ error_info confirmation_callback_t::get_error() const {
194216
} else if (isdigit(*(error.object.c_str()))) {
195217
/* An unnamed array of objects where one or more generated an error, e.g. slash command bulk registration */
196218
e.human_readable += prefix + "- <array>[" + error.object + "]." + error.field + ": " + error.reason + " (" + error.code + ")";
219+
} else if (error.index < 0) {
220+
/* An object field that caused an error */
221+
e.human_readable += prefix + "- " + error.object + '.' + error.field + ": " + error.reason + " (" + error.code + ")";
197222
} else {
198223
/* A named array of objects whre a field in the object has an error */
199224
e.human_readable += prefix + "- " + error.object + "[" + std::to_string(error.index) + "]." + error.field + ": " + error.reason + " (" + error.code + ")";

0 commit comments

Comments
 (0)