Skip to content

ECB SDW API drops Content-Type header when passing dsd= parameter #257

@jpommerening

Description

@jpommerening

Hi!

I've been using pandaSDMX (to great success) to fetch exchange rates and more from the ECBs statistical data warehouse "SDW".

Recently (around February 24th or 25th), something on the ECB API has changed, causing my regular data imports to fail.

(I've also reported that problem to them using their contact form. Waiting to see what'll happen.)

Here's what I have found out until now:

When fetching data without an Accept header, the API returns a Content-Type: application/vnd.sdmx.genericdata+xml;version=2.1 header.
When fetching data with an Accept: application/vnd.sdmx.genericdata+xml;version=2.1 header, the API returns no Content-Type header at all.
This triggers an error in pandaSDMX.

To reproduce:

# result includes Content-Type header
curl -I 'https://data-api.ecb.europa.eu/service/data/EXR/D.USD.EUR.SP00.A?startPeriod=2025-01-01'

# result is lacking Content-Type header
curl -I -H'Accept: application/vnd.sdmx.genericdata+xml;version=2.1' 'https://data-api.ecb.europa.eu/service/data/EXR/D.USD.EUR.SP00.A?startPeriod=2025-01-01'

The pandaSDMX equivalent in python:

import pandasdmx as sdmx

ecb = sdmx.Request('ECB')
exr = ecb.dataflow('EXR')

# works, because it's not sending an Accept header due to not passing a data structure definition
data = ecb.data('EXR', key='D.USD.EUR.SP00.A', params={'startPeriod':'2025-01-01'})

# fails, because it's sending an Accept header
data = ecb.data('EXR', dsd=exr.structure.ECB_EXR1, key='D.USD.EUR.SP00.A', params={'startPeriod':'2025-01-01'})

The error happens when get_reader_for_content_type(content_type) is called with None because of the missing Content-Type header.

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/.../venv/lib/python3.11/site-packages/pandasdmx/api.py", line 498, in get
    Reader = get_reader_for_content_type(content_type)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/.../venv/lib/python3.11/site-packages/pandasdmx/reader/__init__.py", line 45, in get_reader_for_content_type
    if cls.supports_content_type(ctype):
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/.../venv/lib/python3.11/site-packages/pandasdmx/reader/base.py", line 40, in supports_content_type
    other = parse_content_type(value)
            ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/.../venv/lib/python3.11/site-packages/pandasdmx/util.py", line 374, in parse_content_type
    tokens = value.split(";")
             ^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'split'

I'm not 100% sure if this can be safely handled in pandaSDMX. Maybe have a default reader to use when no Content-Type header is returned? Maybe guess that Content-Type equals Accept if it's missing?
Both sound sub-optimal. I hope that ECB ship fix it on their end, but I don't know if that will happen, even though I asked very nicely.

Also, you're using ECB for some examples in the documentation. Those might fail because of this as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions