diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index f72d2b0..5c03e4d 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,16 @@
 Changelog
 ---------
 
+6.1.1 (Unreleased)
+******************
+
+Bug fixes:
+
+* Failure to validate flask headers would produce error data which contained
+  tuples as keys, and was therefore not JSON-serializable. (:issue:`500`)
+  These errors will now extract the headername as the key correctly.
+  Thanks to :user:`shughes-uk` for reporting.
+
 6.1.0 (2020-04-05)
 ******************
 
diff --git a/src/webargs/multidictproxy.py b/src/webargs/multidictproxy.py
index 6d7c8cc..54e955b 100644
--- a/src/webargs/multidictproxy.py
+++ b/src/webargs/multidictproxy.py
@@ -62,7 +62,13 @@ class MultiDictProxy(Mapping):
         return getattr(self.data, name)
 
     def __iter__(self):
-        return iter(self.data)
+        for x in iter(self.data):
+            # special case for header dicts which produce an iterator of tuples
+            # instead of an iterator of strings
+            if isinstance(x, tuple):
+                yield x[0]
+            else:
+                yield x
 
     def __contains__(self, x):
         return x in self.data

Errors while validating arguments in headers result in a flask crash
If you make a view with header arguments `@bp.arguments(someschema, location='headers')`
Then feed it headers that are not defined in the schema, it will (rightfully) cause a schema validation error, however the error created includes the entire header tuple as a dictionary key, instead of just the 'key' (tuple position 0). This causes flask to error out while trying to convert the response to a valid JSON response.

This is the response returned (grabbed this with a pydb)
```python
{
    "code": 422,
    "status": "Unprocessable Entity",
    "errors": {"headers": {("Someheader", "someval"): ["Unknown field."]}},
}
```
This is the stack trace flask produces, which I have included so people searching it will hopefully find their way here.

```python
../../../../miniconda3/lib/python3.7/site-packages/werkzeug/test.py:1006: in get
    return self.open(*args, **kw)
nomitall/api/tests/_client.py:37: in open
    return super().open(*args, **kwargs)
../../../../miniconda3/lib/python3.7/site-packages/flask/testing.py:227: in open
    follow_redirects=follow_redirects,
../../../../miniconda3/lib/python3.7/site-packages/werkzeug/test.py:970: in open
    response = self.run_wsgi_app(environ.copy(), buffered=buffered)
../../../../miniconda3/lib/python3.7/site-packages/werkzeug/test.py:861: in run_wsgi_app
    rv = run_wsgi_app(self.application, environ, buffered=buffered)
../../../../miniconda3/lib/python3.7/site-packages/werkzeug/test.py:1096: in run_wsgi_app
    app_rv = app(environ, start_response)
../../../../miniconda3/lib/python3.7/site-packages/flask/app.py:2463: in __call__
    return self.wsgi_app(environ, start_response)
../../../../miniconda3/lib/python3.7/site-packages/flask/app.py:2449: in wsgi_app
    response = self.handle_exception(e)
../../../../miniconda3/lib/python3.7/site-packages/flask/app.py:1866: in handle_exception
    reraise(exc_type, exc_value, tb)
../../../../miniconda3/lib/python3.7/site-packages/flask/_compat.py:39: in reraise
    raise value
../../../../miniconda3/lib/python3.7/site-packages/flask/app.py:2446: in wsgi_app
    response = self.full_dispatch_request()
../../../../miniconda3/lib/python3.7/site-packages/flask/app.py:1952: in full_dispatch_request
    return self.finalize_request(rv)
../../../../miniconda3/lib/python3.7/site-packages/flask/app.py:1967: in finalize_request
    response = self.make_response(rv)
../../../../miniconda3/lib/python3.7/site-packages/flask/app.py:2111: in make_response
    rv = jsonify(rv)
../../../../miniconda3/lib/python3.7/site-packages/flask/json/__init__.py:370: in jsonify
    dumps(data, indent=indent, separators=separators) + "\n",
../../../../miniconda3/lib/python3.7/site-packages/flask/json/__init__.py:211: in dumps
    rv = _json.dumps(obj, **kwargs)
../../../../miniconda3/lib/python3.7/site-packages/simplejson/__init__.py:412: in dumps
    **kw).encode(obj)
../../../../miniconda3/lib/python3.7/site-packages/simplejson/encoder.py:298: in encode
    chunks = list(chunks)
../../../../miniconda3/lib/python3.7/site-packages/simplejson/encoder.py:696: in _iterencode
    for chunk in _iterencode_dict(o, _current_indent_level):
../../../../miniconda3/lib/python3.7/site-packages/simplejson/encoder.py:652: in _iterencode_dict
    for chunk in chunks:
../../../../miniconda3/lib/python3.7/site-packages/simplejson/encoder.py:652: in _iterencode_dict
    for chunk in chunks:
../../../../miniconda3/lib/python3.7/site-packages/simplejson/encoder.py:598: in _iterencode_dict
    k = _stringify_key(k)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

key = ("Someheader", "someval")

    def _stringify_key(key):
        if isinstance(key, string_types): # pragma: no cover
            pass
        elif _PY3 and isinstance(key, bytes) and _encoding is not None:
            key = str(key, _encoding)
        elif isinstance(key, float):
            key = _floatstr(key)
        elif key is True:
            key = 'true'
        elif key is False:
            key = 'false'
        elif key is None:
            key = 'null'
        elif isinstance(key, integer_types):
            if type(key) not in integer_types:
                # See marshmallow-code/flask-smorest#118, do not trust custom str/repr
                key = int(key)
            key = str(key)
        elif _use_decimal and isinstance(key, Decimal):
            key = str(key)
        elif _skipkeys:
            key = None
        else:
            raise TypeError('keys must be str, int, float, bool or None, '
>                           'not %s' % key.__class__.__name__)
E           TypeError: keys must be str, int, float, bool or None, not tuple

../../../../miniconda3/lib/python3.7/site-packages/simplejson/encoder.py:568: TypeError
```

I'm not sure there is a good workaround apart from disabling schema validation.

If this issue is unclear please ask for further explanation and i'll sink some time into creating some self contained reproduction code.
diff --git a/tests/apps/flask_app.py b/tests/apps/flask_app.py
index 232e715..736224c 100644
--- a/tests/apps/flask_app.py
+++ b/tests/apps/flask_app.py
@@ -126,6 +126,14 @@ def echo_headers():
     return J(parser.parse(hello_exclude_schema, location="headers"))
 
 
+@app.route("/echo_headers_raising")
+@use_args(HelloSchema(**strict_kwargs), location="headers")
+def echo_headers_raising(args):
+    # as above, but in this case, don't use the exclude schema (so unexpected
+    # headers will raise errors)
+    return J(args)
+
+
 @app.route("/echo_cookie")
 def echo_cookie():
     return J(parser.parse(hello_args, request, location="cookies"))
diff --git a/tests/test_flaskparser.py b/tests/test_flaskparser.py
index f8ccf36..3429992 100644
--- a/tests/test_flaskparser.py
+++ b/tests/test_flaskparser.py
@@ -67,6 +67,21 @@ class TestFlaskParser(CommonTestCase):
         res = testapp.post_json("/echo_nested_many_data_key", {})
         assert res.json == {}
 
+    # regression test for
+    # https://github.com/marshmallow-code/webargs/issues/500
+    def test_parsing_unexpected_headers_when_raising(self, testapp):
+        res = testapp.get(
+            "/echo_headers_raising", expect_errors=True, headers={"X-Unexpected": "foo"}
+        )
+        # under marshmallow 2 this is allowed and works
+        if MARSHMALLOW_VERSION_INFO[0] < 3:
+            assert res.json == {"name": "World"}
+        # but on ma3 it's supposed to be a validation error
+        else:
+            assert res.status_code == 422
+            assert "headers" in res.json
+            assert "X-Unexpected" in set(res.json["headers"].keys())
+
 
 @mock.patch("webargs.flaskparser.abort")
 def test_abort_called_on_validation_error(mock_abort):

pip install -e .[dev]
parse_log_pytest
pytest
pytest
3.9
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
aiohappyeyeballs==2.6.1
aiohttp==3.11.14
aiosignal==1.3.2
asgiref==3.8.1
async-timeout==5.0.1
attrs==25.3.0
beautifulsoup4==4.13.3
blinker==1.9.0
bottle==0.13.2
cachetools==5.5.2
cfgv==3.4.0
chardet==5.2.0
click==8.1.8
colorama==0.4.6
distlib==0.3.9
Django==4.2.20
exceptiongroup @ file:///croot/exceptiongroup_1706031385326/work
falcon==4.0.2
filelock==3.18.0
flake8==3.8.3
flake8-bugbear==20.1.4
Flask==3.1.0
frozenlist==1.5.0
hupper==1.12.1
identify==2.6.9
idna==3.10
importlib_metadata==8.6.1
iniconfig @ file:///home/linux1/recipes/ci/iniconfig_1610983019677/work
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.2
marshmallow==3.26.1
mccabe==0.6.1
multidict==6.2.0
mypy==0.782
mypy_extensions==0.4.4
nodeenv==1.9.1
packaging @ file:///croot/packaging_1734472117206/work
PasteDeploy==3.1.0
plaster==1.1.2
plaster-pastedeploy==1.0.1
platformdirs==4.3.7
pluggy @ file:///croot/pluggy_1733169602837/work
pre-commit==2.21.0
propcache==0.3.1
pycodestyle==2.6.0
pyflakes==2.2.0
pyproject-api==1.9.0
pyramid==2.0.2
pytest @ file:///croot/pytest_1738938843180/work
pytest-aiohttp==1.1.0
pytest-asyncio==0.26.0
PyYAML==6.0.2
six==1.17.0
soupsieve==2.6
sqlparse==0.5.3
tomli==2.2.1
tornado==6.4.2
tox==4.25.0
translationstring==1.4
typed-ast==1.4.3
typing_extensions==4.13.0
venusian==3.1.1
virtualenv==20.29.3
waitress==3.0.2
webapp2==3.0.0b1
-e git+https://github.com/marshmallow-code/webargs.git@c8c9cc15e390641fb48f94054157addf22629858#egg=webargs
WebOb==1.8.9
WebTest==2.0.35
webtest-aiohttp==2.0.0
Werkzeug==3.1.3
yarl==1.18.3
zipp==3.21.0
zope.deprecation==5.1
zope.interface==7.2

name: webargs
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - exceptiongroup=1.2.0=py39h06a4308_0
  - iniconfig=1.1.1=pyhd3eb1b0_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - packaging=24.2=py39h06a4308_0
  - pip=25.0=py39h06a4308_0
  - pluggy=1.5.0=py39h06a4308_0
  - pytest=8.3.4=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - aiohappyeyeballs==2.6.1
      - aiohttp==3.11.14
      - aiosignal==1.3.2
      - asgiref==3.8.1
      - async-timeout==5.0.1
      - attrs==25.3.0
      - beautifulsoup4==4.13.3
      - blinker==1.9.0
      - bottle==0.13.2
      - cachetools==5.5.2
      - cfgv==3.4.0
      - chardet==5.2.0
      - click==8.1.8
      - colorama==0.4.6
      - distlib==0.3.9
      - django==4.2.20
      - falcon==4.0.2
      - filelock==3.18.0
      - flake8==3.8.3
      - flake8-bugbear==20.1.4
      - flask==3.1.0
      - frozenlist==1.5.0
      - hupper==1.12.1
      - identify==2.6.9
      - idna==3.10
      - importlib-metadata==8.6.1
      - itsdangerous==2.2.0
      - jinja2==3.1.6
      - markupsafe==3.0.2
      - marshmallow==3.26.1
      - mccabe==0.6.1
      - multidict==6.2.0
      - mypy==0.782
      - mypy-extensions==0.4.4
      - nodeenv==1.9.1
      - pastedeploy==3.1.0
      - plaster==1.1.2
      - plaster-pastedeploy==1.0.1
      - platformdirs==4.3.7
      - pre-commit==2.21.0
      - propcache==0.3.1
      - pycodestyle==2.6.0
      - pyflakes==2.2.0
      - pyproject-api==1.9.0
      - pyramid==2.0.2
      - pytest-aiohttp==1.1.0
      - pytest-asyncio==0.26.0
      - pyyaml==6.0.2
      - six==1.17.0
      - soupsieve==2.6
      - sqlparse==0.5.3
      - tomli==2.2.1
      - tornado==6.4.2
      - tox==4.25.0
      - translationstring==1.4
      - typed-ast==1.4.3
      - typing-extensions==4.13.0
      - venusian==3.1.1
      - virtualenv==20.29.3
      - waitress==3.0.2
      - webapp2==3.0.0b1
      - webob==1.8.9
      - webtest==2.0.35
      - webtest-aiohttp==2.0.0
      - werkzeug==3.1.3
      - yarl==1.18.3
      - zipp==3.21.0
      - zope-deprecation==5.1
      - zope-interface==7.2
prefix: /opt/conda/envs/webargs

tests/test_flaskparser.py::TestFlaskParser::test_parsing_unexpected_headers_when_raising
tests/test_flaskparser.py::TestFlaskParser::test_parse_querystring_args tests/test_flaskparser.py::TestFlaskParser::test_parse_form tests/test_flaskparser.py::TestFlaskParser::test_parse_json tests/test_flaskparser.py::TestFlaskParser::test_parse_json_missing tests/test_flaskparser.py::TestFlaskParser::test_parse_json_or_form tests/test_flaskparser.py::TestFlaskParser::test_parse_querystring_default tests/test_flaskparser.py::TestFlaskParser::test_parse_json_default tests/test_flaskparser.py::TestFlaskParser::test_parse_json_with_charset tests/test_flaskparser.py::TestFlaskParser::test_parse_json_with_vendor_media_type tests/test_flaskparser.py::TestFlaskParser::test_parse_ignore_extra_data tests/test_flaskparser.py::TestFlaskParser::test_parse_json_empty tests/test_flaskparser.py::TestFlaskParser::test_parse_json_error_unexpected_int tests/test_flaskparser.py::TestFlaskParser::test_parse_json_error_unexpected_list tests/test_flaskparser.py::TestFlaskParser::test_parse_json_many_schema_invalid_input tests/test_flaskparser.py::TestFlaskParser::test_parse_json_many_schema tests/test_flaskparser.py::TestFlaskParser::test_parse_json_many_schema_error_malformed_data tests/test_flaskparser.py::TestFlaskParser::test_parsing_form_default tests/test_flaskparser.py::TestFlaskParser::test_parse_querystring_multiple tests/test_flaskparser.py::TestFlaskParser::test_parse_querystring_multiple_single_value tests/test_flaskparser.py::TestFlaskParser::test_parse_form_multiple tests/test_flaskparser.py::TestFlaskParser::test_parse_json_list tests/test_flaskparser.py::TestFlaskParser::test_parse_json_list_error_malformed_data tests/test_flaskparser.py::TestFlaskParser::test_parse_json_with_nonascii_chars tests/test_flaskparser.py::TestFlaskParser::test_parse_json_with_nonutf8_chars tests/test_flaskparser.py::TestFlaskParser::test_validation_error_returns_422_response tests/test_flaskparser.py::TestFlaskParser::test_user_validation_error_returns_422_response_by_default tests/test_flaskparser.py::TestFlaskParser::test_use_args_decorator tests/test_flaskparser.py::TestFlaskParser::test_use_args_with_path_param tests/test_flaskparser.py::TestFlaskParser::test_use_args_with_validation tests/test_flaskparser.py::TestFlaskParser::test_use_kwargs_decorator tests/test_flaskparser.py::TestFlaskParser::test_use_kwargs_with_path_param tests/test_flaskparser.py::TestFlaskParser::test_parsing_headers tests/test_flaskparser.py::TestFlaskParser::test_parsing_cookies tests/test_flaskparser.py::TestFlaskParser::test_parse_nested_json tests/test_flaskparser.py::TestFlaskParser::test_parse_nested_many_json tests/test_flaskparser.py::TestFlaskParser::test_parse_nested_many_missing tests/test_flaskparser.py::TestFlaskParser::test_parse_files tests/test_flaskparser.py::TestFlaskParser::test_empty_json tests/test_flaskparser.py::TestFlaskParser::test_empty_json_with_headers tests/test_flaskparser.py::TestFlaskParser::test_invalid_json tests/test_flaskparser.py::TestFlaskParser::test_content_type_mismatch[/echo_json-{"name": tests/test_flaskparser.py::TestFlaskParser::test_content_type_mismatch[/echo_form-payload1-application/json] tests/test_flaskparser.py::TestFlaskParser::test_parsing_view_args tests/test_flaskparser.py::TestFlaskParser::test_parsing_invalid_view_arg tests/test_flaskparser.py::TestFlaskParser::test_use_args_with_view_args_parsing tests/test_flaskparser.py::TestFlaskParser::test_use_args_on_a_method_view tests/test_flaskparser.py::TestFlaskParser::test_use_kwargs_on_a_method_view tests/test_flaskparser.py::TestFlaskParser::test_use_kwargs_with_missing_data tests/test_flaskparser.py::TestFlaskParser::test_nested_many_with_data_key tests/test_flaskparser.py::test_abort_called_on_validation_error tests/test_flaskparser.py::test_load_json_returns_missing_if_no_data[None] tests/test_flaskparser.py::test_load_json_returns_missing_if_no_data[application/json] tests/test_flaskparser.py::test_abort_with_message tests/test_flaskparser.py::test_abort_has_serializable_data
CHANGELOG.rst src/webargs/multidictproxy.py
CHANGELOG.rst src/webargs/multidictproxy.py