# Buggy code
def get_image_list(self, query_result, coordinates, radius):
    """
    Function to map the results of a CADC query into URLs to
    corresponding data and cutouts that can be later downloaded.

    The function uses the IVOA DataLink Service
    (http://www.ivoa.net/documents/DataLink/) implemented at the CADC.
    It works directly with the results produced by `query_region` and
    `query_name` but in principle it can work with other query
    results produced with the Cadc query as long as the results
    contain the 'publisherID' column. This column is part of the
    'caom2.Plane' table.

    Parameters
    ----------
    query_result : A `~astropy.table.Table` object
        Result returned by `query_region` or
        `query_name`. In general, the result of any
        CADC TAP query that contains the 'publisherID'
        column can be used here.
    coordinates : str or `astropy.coordinates`.
        Center of the cutout area.
    radius : str or `astropy.units.Quantity`.
        The radius of the cutout area.

    Returns
    -------
    list : A list of URLs to cutout data.
    """

    if not query_result:
        raise AttributeError("Missing query_result argument")

    parsed_coordinates = commons.parse_coordinates(coordinates).fk5
    ra = parsed_coordinates.ra.degree
    dec = parsed_coordinates.dec.degree
    cutout_params = {"POS": "CIRCLE {} {} {}".format(ra, dec, radius)}

    try:
        publisher_ids = query_result["publisherID"]
    except KeyError:
        raise AttributeError("publisherID column missing from query_result argument")

    result = []

    # Send datalink requests in batches of 20 publisher ids
    batch_size = 20

    # Iterate through list of sublists to send datalink requests in batches
    for pid_sublist in (
        publisher_ids[pos : pos + batch_size]
        for pos in range(0, len(publisher_ids), batch_size)
    ):
        datalink = pyvo.dal.adhoc.DatalinkResults.from_result_url(
            "{}?{}".format(self.data_link_url, urlencode({"ID": pid_sublist}, True))
        )
        for service_def in datalink.bysemantics("#cutout"):
            access_url = service_def.access_url.decode("ascii")
            if "/sync" in access_url:
                service_params = service_def.input_params
                input_params = {
                    param.name: param.value
                    for param in service_params
                    if param.name in ["ID", "RUNID"]
                }
                input_params.update(cutout_params)
                result.append("{}?{}".format(access_url, urlencode(input_params)))

    return result


# Traceback (HTTPError)
---------------------------------------------------------------------------
HTTPError                                 Traceback (most recent call last)
<ipython-input-68-f4c802433ee1> in <module>
----> 1 cadc.query_region(c, radius=1*u.deg)

~/anaconda3/lib/python3.7/site-packages/astroquery/utils/class_or_instance.py in f(*args, **kwds)
23         def f(*args, **kwds):
24             if obj is not None:
---> 25                 return self.fn(obj, *args, **kwds)
26             else:
27                 return self.fn(cls, *args, **kwds)

~/anaconda3/lib/python3.7/site-packages/astroquery/utils/process_asyncs.py in newmethod(self, *args, **kwargs)
24             verbose = kwargs.pop('verbose', False)
25
---> 26             response = getattr(self, async_method_name)(*args, **kwargs)
27             if kwargs.get('get_query_payload') or kwargs.get('field_help'):
28                 return response

~/anaconda3/lib/python3.7/site-packages/astroquery/utils/class_or_instance.py in f(*args, **kwds)
23         def f(*args, **kwds):
24             if obj is not None:
---> 25                 return self.fn(obj, *args, **kwds)
26             else:
27                 return self.fn(cls, *args, **kwds)

~/anaconda3/lib/python3.7/site-packages/astroquery/cadc/core.py in query_region_async(self, coordinates, radius, collection, get_query_payload)
165         if get_query_payload:
166             return request_payload
--> 167         response = self.run_query(request_payload['query'], operation='sync')
168         return response
169

~/anaconda3/lib/python3.7/site-packages/astroquery/cadc/core.py in run_query(self, query, operation, output_file, output_format, verbose, background, upload_resource, upload_table_name)
346                 dump_to_file=save_to_file,
347                 upload_resource=upload_resource,
--> 348                 upload_table_name=upload_table_name)
349             op = False
350         elif operation == 'async':

~/anaconda3/lib/python3.7/site-packages/astroquery/utils/tap/core.py in launch_job(self, query, name, output_file, output_format, verbose, dump_to_file, upload_resource, upload_table_name)
239             if dump_to_file:
240                 self.__connHandler.dump_to_file(suitableOutputFile, response)
--> 241             raise requests.exceptions.HTTPError(response.reason)
242         else:
243             if verbose:

HTTPError: Bad Request

# Fixed code
def get_image_list(self, query_result, coordinates, radius):
    """
    Function to map the results of a CADC query into URLs to
    corresponding data and cutouts that can be later downloaded.

    The function uses the IVOA DataLink Service
    (http://www.ivoa.net/documents/DataLink/) implemented at the CADC.
    It works directly with the results produced by `query_region` and
    `query_name` but in principle it can work with other query
    results produced with the Cadc query as long as the results
    contain the 'publisherID' column. This column is part of the
    'caom2.Plane' table.

    Parameters
    ----------
    query_result : A `~astropy.table.Table` object
        Result returned by `query_region` or
        `query_name`. In general, the result of any
        CADC TAP query that contains the 'publisherID'
        column can be used here.
    coordinates : str or `astropy.coordinates`.
        Center of the cutout area.
    radius : str or `astropy.units.Quantity`.
        The radius of the cutout area.

    Returns
    -------
    list : A list of URLs to cutout data.
    """

    if not query_result:
        raise AttributeError("Missing query_result argument")

    parsed_coordinates = commons.parse_coordinates(coordinates).fk5
    radius_deg = commons.radius_to_unit(radius, unit="degree")
    ra = parsed_coordinates.ra.degree
    dec = parsed_coordinates.dec.degree
    cutout_params = {"POS": "CIRCLE {} {} {}".format(ra, dec, radius_deg)}

    try:
        publisher_ids = query_result["publisherID"]
    except KeyError:
        raise AttributeError("publisherID column missing from query_result argument")

    result = []

    # Send datalink requests in batches of 20 publisher ids
    batch_size = 20

    # Iterate through list of sublists to send datalink requests in batches
    for pid_sublist in (
        publisher_ids[pos : pos + batch_size]
        for pos in range(0, len(publisher_ids), batch_size)
    ):
        datalink = pyvo.dal.adhoc.DatalinkResults.from_result_url(
            "{}?{}".format(self.data_link_url, urlencode({"ID": pid_sublist}, True))
        )
        for service_def in datalink.bysemantics("#cutout"):
            access_url = service_def.access_url.decode("ascii")
            if "/sync" in access_url:
                service_params = service_def.input_params
                input_params = {
                    param.name: param.value
                    for param in service_params
                    if param.name in ["ID", "RUNID"]
                }
                input_params.update(cutout_params)
                result.append("{}?{}".format(access_url, urlencode(input_params)))

    return result