Repository: astropy/astroquery

Issue:
Handling  No astronomical object found response
When I run the following script that queries a tiny sky region where Simbad has no object:

```python
from astroquery.simbad import Simbad
from astropy.coordinates import SkyCoord, search_around_sky, Angle
import astropy.units as u

ra = 0
dec = -90
output_table= Simbad.query_region(SkyCoord(ra, dec,unit=(u.deg, u.deg), frame='icrs'), radius=0.01*u.arcsec)
```

This code raises the following warning:

```
WARNING: BlankResponseWarning: Warning: The script line number 3 raised an error (recorded in the `errors` attribute of the result table): '0:00:00 -90:00:00': No astronomical object found : [astroquery.simbad.core]
```
The problem is that `output_table` is `None`. 
There is no way to grab by software the reason of the failure except by parsing the WARNING message (awkward/ugly).

There are 2 options to improve this issue:
- The query region  could return a tuple such as e.g. `(error_status, table)`
- The method should  be refactored in order to return a VOTable in any case (as announced by the warning)

Discussion:

Patch:
diff --git a/astroquery/simbad/core.py b/astroquery/simbad/core.py
index 1f901aa3..9f16ea12 100644
--- a/astroquery/simbad/core.py
+++ b/astroquery/simbad/core.py
@@ -18,7 +18,7 @@ from astropy.utils.decorators import deprecated_renamed_argument
 
 from astroquery.query import BaseVOQuery
 from astroquery.utils import commons
-from astroquery.exceptions import LargeQueryWarning
+from astroquery.exceptions import LargeQueryWarning, NoResultsWarning
 from astroquery.simbad.utils import (_catch_deprecated_fields_with_arguments,
                                      _wildcard_to_regexp, CriteriaTranslator,
                                      query_criteria_fields)
@@ -1397,7 +1397,7 @@ class SimbadClass(BaseVOQuery):
         `~astropy.table.Table`
             The result of the query to SIMBAD.
         """
-        top = f" TOP {top}" if top != -1 else ""
+        top_part = f" TOP {top}" if top != -1 else ""
 
         # columns
         input_columns = [f'{column.table}."{column.name}" AS "{column.alias}"' if column.alias is not None
@@ -1425,9 +1425,16 @@ class SimbadClass(BaseVOQuery):
         else:
             criteria = ""
 
-        query = f"SELECT{top}{columns} FROM {from_table}{join}{criteria}"
+        query = f"SELECT{top_part}{columns} FROM {from_table}{join}{criteria}"
 
-        return self.query_tap(query, get_query_payload=get_query_payload, **uploads)
+        response = self.query_tap(query, get_query_payload=get_query_payload,
+                                  maxrec=self.hardlimit,
+                                  **uploads)
+
+        if len(response) == 0 and top != 0:
+            warnings.warn("The request executed correctly, but there was no data corresponding"
+                          " to these criteria in SIMBAD", NoResultsWarning)
+        return response
 
 
 Simbad = SimbadClass()
diff --git a/docs/simbad/simbad.rst b/docs/simbad/simbad.rst
index f928d91f..5eca9e63 100644
--- a/docs/simbad/simbad.rst
+++ b/docs/simbad/simbad.rst
@@ -467,28 +467,29 @@ with:
     >>> from astroquery.simbad import Simbad
     >>> Simbad.list_votable_fields()[["name", "description"]]
     <Table length=115>
-         name                                     description
-        object                                       object
-    ------------- ----------------------------------------------------------------------------
-      mesDiameter                                             Collection of stellar diameters.
-            mesPM                                                Collection of proper motions.
-           mesISO                              Infrared Space Observatory (ISO) observing log.
-           mesSpT                                                Collection of spectral types.
-        allfluxes                             all flux/magnitudes U,B,V,I,J,H,K,u_,g_,r_,i_,z_
-            ident                                        Identifiers of an astronomical object
-             flux                      Magnitude/Flux information about an astronomical object
-           mesPLX                                      Collection of trigonometric parallaxes.
-         otypedef                               all names and definitions for the object types
-              ...                                                                          ...
-                u                                                             Magnitude SDSS u
-                g                                                             Magnitude SDSS g
-                r                                                             Magnitude SDSS r
-                i                                                             Magnitude SDSS i
-                z                                                             Magnitude SDSS z
-                G                                                             Magnitude Gaia G
-            F150W                                                            JWST NIRCam F150W
-            F200W                                                            JWST NIRCam F200W
-            F444W                                                            JWST NIRCan F444W
+        name                          description                      
+       object                            object                        
+    ----------- -------------------------------------------------------
+    mesDiameter                        Collection of stellar diameters.
+          mesPM                           Collection of proper motions.
+         mesISO         Infrared Space Observatory (ISO) observing log.
+         mesSpT                           Collection of spectral types.
+      allfluxes        all flux/magnitudes U,B,V,I,J,H,K,u_,g_,r_,i_,z_
+          ident                   Identifiers of an astronomical object
+           flux Magnitude/Flux information about an astronomical object
+         mesPLX                 Collection of trigonometric parallaxes.
+       otypedef          all names and definitions for the object types
+            ...                                                     ...
+              K                                             Magnitude K
+              u                                        Magnitude SDSS u
+              g                                        Magnitude SDSS g
+              r                                        Magnitude SDSS r
+              i                                        Magnitude SDSS i
+              z                                        Magnitude SDSS z
+              G                                        Magnitude Gaia G
+          F150W                                       JWST NIRCam F150W
+          F200W                                       JWST NIRCam F200W
+          F444W                                       JWST NIRCan F444W
 
 You can also access a single field description with
 `~astroquery.simbad.SimbadClass.get_field_description`


Test patch:
diff --git a/astroquery/simbad/tests/test_simbad.py b/astroquery/simbad/tests/test_simbad.py
index 0e23198a..aec4b23c 100644
--- a/astroquery/simbad/tests/test_simbad.py
+++ b/astroquery/simbad/tests/test_simbad.py
@@ -13,7 +13,7 @@ import pytest
 
 from ... import simbad
 from .test_simbad_remote import multicoords
-from astroquery.exceptions import LargeQueryWarning
+from astroquery.exceptions import LargeQueryWarning, NoResultsWarning
 
 
 GALACTIC_COORDS = SkyCoord(l=-67.02084 * u.deg, b=-29.75447 * u.deg, frame="galactic")
@@ -486,6 +486,16 @@ def test_query_tap_cache_call(monkeypatch):
     assert simbad.Simbad.query_tap("select top 1 * from basic") == msg
 
 
+@pytest.mark.usefixtures("_mock_simbad_class")
+def test_empty_response_warns(monkeypatch):
+    # return something of length zero
+    monkeypatch.setattr(simbad.core.Simbad, "query_tap", lambda _, get_query_payload, maxrec: [])
+    msg = ("The request executed correctly, but there was no data corresponding to these"
+           " criteria in SIMBAD")
+    with pytest.warns(NoResultsWarning, match=msg):
+        simbad.core.Simbad.query_catalog("unknown_catalog")
+
+
 # ---------------------------------------------------
 # Test the adql string for query_tap helper functions
 # ---------------------------------------------------
diff --git a/astroquery/simbad/tests/test_simbad_remote.py b/astroquery/simbad/tests/test_simbad_remote.py
index 1c49fbe6..d5084940 100644
--- a/astroquery/simbad/tests/test_simbad_remote.py
+++ b/astroquery/simbad/tests/test_simbad_remote.py
@@ -6,6 +6,7 @@ import astropy.units as u
 from astropy.utils.exceptions import AstropyDeprecationWarning
 from astropy.table import Table
 
+from astroquery.exceptions import NoResultsWarning
 from astroquery.simbad import Simbad
 from astroquery.simbad.core import _cached_query_tap, _Column, _Join
 
@@ -141,6 +142,11 @@ class TestSimbad:
         Simbad.clear_cache()
         assert _cached_query_tap.cache_info().currsize == 0
 
+    def test_empty_response_warns(self):
+        with pytest.warns(NoResultsWarning, match="The request executed correctly, but *"):
+            # a catalog that does not exists should return an empty response
+            Simbad.query_catalog("unknown_catalog")
+
     # ----------------------------------
 
     def test_simbad_list_tables(self):