Repository: conan-io/conan
Pull request #12633 (2022-11-30 01:22:36)

Add context for error; fix for Issue #9751
Changelog: (Feature | Fix | Bugfix): Describe here your pull request
Docs: https://github.com/conan-io/docs/pull/XXXX

- [x] Refer to the issue that supports this Pull Request.
- [x] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
- [x] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).
- [x] I've followed the PEP8 style guides for Python code.
- [ ] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one. 

<sup>**Note:** By default this PR will skip the slower tests and will use a limited set of python versions. Check [here](https://github.com/conan-io/conan/blob/develop/.github/PR_INCREASE_TESTING.md) how to increase the testing level by writing some tags in the current PR body text.</sup>


CLAassistant: [![CLA assistant check](https://cla-assistant.io/pull/badge/not_signed)](https://cla-assistant.io/conan-io/conan?pullRequest=12633) <br/>Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our [Contributor License Agreement](https://cla-assistant.io/conan-io/conan?pullRequest=12633) before we can accept your contribution.<br/><sub>You have signed the CLA already but the status is still pending? Let us [recheck](https://cla-assistant.io/check/conan-io/conan?pullRequest=12633) it.</sub>
adam248: Fixes Issue #9751
adam248: > It would be nice to add some test to the suite that covers this, there are some tests mocking the server responses, probably they can be extended. Have a look if possible, and if not, let us know, we might try to contribute it.

Will look into writing a test once you are happy with my Exception handling methodology, just let us know and I will try to add it to this pull request.
adam248: I believe all issues have been addressed with my final commit. 
Good to go❓ 

Patch:
diff --git a/conans/client/rest/rest_client_common.py b/conans/client/rest/rest_client_common.py
index 3c4e138cb..c0fdb1237 100644
--- a/conans/client/rest/rest_client_common.py
+++ b/conans/client/rest/rest_client_common.py
@@ -242,7 +242,12 @@ class RestCommonMethods(object):
         """
         url = self.router.search(pattern, ignorecase)
         response = self.get_json(url)["results"]
-        return [ConanFileReference.loads(reference) for reference in response]
+        try:
+            return [ConanFileReference.loads(reference) for reference in response]
+        except TypeError as te:
+            raise ConanException("Unexpected response from server.\n"
+                                 "URL: `{}`\n"
+                                 "Expected an iterable, but got {}.".format(url, type(response)))
 
     def search_packages(self, ref):
         """Client is filtering by the query"""


Test patch:
diff --git a/conans/test/unittests/client/rest/rest_client_v1/test_get_package_manifest.py b/conans/test/unittests/client/rest/rest_client_v1/test_get_package_manifest.py
index f85e549b4..b03ca574f 100644
--- a/conans/test/unittests/client/rest/rest_client_v1/test_get_package_manifest.py
+++ b/conans/test/unittests/client/rest/rest_client_v1/test_get_package_manifest.py
@@ -33,3 +33,15 @@ class GetPackageManifestTestCase(unittest.TestCase):
                           " from remote ({})".format(pref, remote_url),
                           str(exc.exception))
             self.assertIn("invalid literal for int() with base 10", str(exc.exception))
+
+    def test_unexpected_results_from_search(self):
+        remote_url = "http://some.url"
+        with patch.object(RestV1Methods, "get_json", return_value={"results": None}):
+            v1 = RestV1Methods(remote_url, token=None, custom_headers=None, output=None,
+                               requester=None, config=None, verify_ssl=None)
+            with self.assertRaises(ConanException) as exc:
+                v1.search()
+            
+            self.assertIn("Unexpected response from server.\n"
+                          "URL: `http://some.url/v1/conans/search`\n"
+                          "Expected an iterable, but got <class 'NoneType'>.", str(exc.exception))
\ No newline at end of file
diff --git a/conans/test/unittests/client/rest/rest_client_v2/test_get_package_manifest.py b/conans/test/unittests/client/rest/rest_client_v2/test_get_package_manifest.py
index ba900472c..ab3f128cd 100644
--- a/conans/test/unittests/client/rest/rest_client_v2/test_get_package_manifest.py
+++ b/conans/test/unittests/client/rest/rest_client_v2/test_get_package_manifest.py
@@ -30,3 +30,15 @@ class GetPackageManifestTestCase(unittest.TestCase):
                           " from remote ({})".format(pref.full_str(), remote_url),
                           str(exc.exception))
             self.assertIn("invalid literal for int() with base 10", str(exc.exception))
+
+    def test_unexpected_results_from_search(self):
+        remote_url = "http://some.url"
+        with patch.object(RestV2Methods, "get_json", return_value={"results": None}):
+            v2 = RestV2Methods(remote_url, token=None, custom_headers=None, output=None,
+                               requester=None, config=None, verify_ssl=None)
+            with self.assertRaises(ConanException) as exc:
+                v2.search()
+            
+            self.assertIn("Unexpected response from server.\n"
+                          "URL: `http://some.url/v2/conans/search`\n"
+                          "Expected an iterable, but got <class 'NoneType'>.", str(exc.exception))
\ No newline at end of file