aio-libs/aiohttp · error · ValueError
Gunicorn's style options in form of `%(name)s` are not…
Error message
Gunicorn's style options in form of `%(name)s` are not supported for the log formatting. Please use aiohttp's format specification to configure access log formatting: http://docs.aiohttp.org/en/stable/logging.html#format-specification
What it means
Raised as a ValueError by GunicornWebWorker._get_valid_log_format() when the access-log format string contains a Gunicorn-style `%(name)s` placeholder. aiohttp's AccessLogger uses its own %-spec (e.g. %a %t %r %s %b), not Gunicorn's %(name)s dictionary form, so the worker rejects the incompatible format at startup. The exception bubbles out of _run() and aborts worker boot.
Solutions
- Use aiohttp's format specification: e.g. `%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"` (see http://docs.aiohttp.org/en/stable/logging.html#format-specification).
- Remove the custom access_log_format to fall back to the aiohttp default.
- If you only had Gunicorn's default format string, the worker auto-translates DEFAULT_GUNICORN_LOG_FORMAT to DEFAULT_AIOHTTP_LOG_FORMAT, so leaving it unset is safest.
Example fix
// before
# gunicorn.conf.py
access_log_format = '%(h)s %(l)s %(t)s "%(r)s" %(s)s %(b)s'
// after
access_log_format = '%a %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"'
# or simply omit it to use the aiohttp default Defensive patterns
Strategy: validation
Validate before calling
import re
assert not re.search(r'%\([^)]+\)', access_log_format), \
'use aiohttp access log format, not gunicorn %(name)s' Type guard
def is_aiohttp_log_format(fmt: str) -> bool:
import re
return not re.search(r'%\([^)]+\)s', fmt) Try / catch
# raised at worker boot as ValueError; fix the config rather than catching.
# Validate config before deploy:
try:
assert is_aiohttp_log_format(cfg.access_log_format)
except AssertionError:
cfg.access_log_format = '%a %t "%r" %s %b' Prevention
- Use aiohttp's %-token format spec for access_log_format with the aiohttp worker.
- Leave access_log_format unset to use the aiohttp default.
- Do not copy gunicorn %(name)s format strings from sync-worker configs.
When it happens
Trigger: Passing `--access-logformat '%(h)s %(l)s %(t)s %(r)s %(s)s %(b)s'` (a Gunicorn default-style string that is not exactly DEFAULT_GUNICORN_LOG_FORMAT) to the aiohttp gunicorn worker, or setting `access_log_format` in a gunicorn config file using %(name)s placeholders.
Common situations: Copying a gunicorn access_log_format from a Flask/Django deployment into an aiohttp config; a config file that worked under the sync gunicorn worker but is now pointed at GunicornWebWorker.
Related errors
- SSL is not supported.
- wsgi app should be either Application or async function…
- aiohttp only supports http(s) proxies
- base_url must have a trailing '/'
- compress can not be set if Content-Encoding header is set
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/98132f6e50dd6201.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/worker.py:238
See ssl.SSLSocket.__init__ for more details.
"""
if ssl is None: # pragma: no cover
raise RuntimeError("SSL is not supported.")
ctx = ssl.SSLContext(cfg.ssl_version)
ctx.load_cert_chain(cfg.certfile, cfg.keyfile)
ctx.verify_mode = cfg.cert_reqs
if cfg.ca_certs:
ctx.load_verify_locations(cfg.ca_certs)
if cfg.ciphers:
ctx.set_ciphers(cfg.ciphers)
return ctx
def _get_valid_log_format(self, source_format: str) -> str:
if source_format == self.DEFAULT_GUNICORN_LOG_FORMAT:
return self.DEFAULT_AIOHTTP_LOG_FORMAT
elif re.search(r"%\([^\)]+\)", source_format):
raise ValueError(
"Gunicorn's style options in form of `%(name)s` are not "
"supported for the log formatting. Please use aiohttp's "
"format specification to configure access log formatting: "
"http://docs.aiohttp.org/en/stable/logging.html"
"#format-specification"
)
else:
return source_format
class GunicornUVLoopWebWorker(GunicornWebWorker):
def init_process(self) -> None:
import uvloop
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
super().init_process()
View on GitHub (pinned to d041d4d0fd)