Skip to content

netutil, simple_httpclient: format the ValueError messages in raise#3681

Draft
HrachShah wants to merge 2 commits into
tornadoweb:masterfrom
HrachShah:fix/netutil-simple-httpclient-valueerror-format
Draft

netutil, simple_httpclient: format the ValueError messages in raise#3681
HrachShah wants to merge 2 commits into
tornadoweb:masterfrom
HrachShah:fix/netutil-simple-httpclient-valueerror-format

Conversation

@HrachShah

Copy link
Copy Markdown

What do these changes do?

Two raise ValueError("fmt %s", arg) calls in tornado leaked the literal format string in str(exc) instead of producing a readable error. This PR changes both to raise ValueError("fmt %s" % arg) so the offending file path or auth mode name is visible to a user reading the traceback or a log line.

The pre-fix forms:

  • bind_unix_socket raised ValueError("File %s exists and is not a socket", file). str(e) returned "('File %s exists and is not a socket', '/tmp/foo')" and the actual file path was tucked into e.args[1].
  • _HTTPConnection.run raised ValueError("unsupported auth_mode %s", self.request.auth_mode). A log line of the exception only showed the literal format string; the actual mode name was reachable only via e.args[1].

Are there changes in behavior for the user?

Yes, for the error path. Pre-fix both raised a ValueError whose str(e) was a tuple repr of (format_string, value). Post-fix the str(e) is a single, formatted string that names the offending file or mode. Callers that handle the exception (including log lines that print the message) now see something useful.

No other callers in the tornado tree depend on the old message text; the only assumption is that a ValueError is raised, which is preserved.

Is it a substantial burden for the maintainers to support this?

No. The change is one-character at each raise site (a , becomes " % ), and the new error is strictly more useful than the old one. No public API or signature changes; no behavior change on the success path.

Related issue number

None — these are the remaining two ValueError(fmt, arg) instances in the package, spotted while reading the recent web, websocket: format ValueError messages in raise change.

Checklist

  • I think the code is well written
  • Unit tests for the changes exist
  • Documentation reflects the changes
    • N/A — no user-facing docs reference these specific error messages
  • If you provide code modification, please add yourself to CONTRIBUTORS.txt
    • N/A — first-time contributor
  • Add a new news fragment into the CHANGES/ folder
    • N/A — tornado uses CHANGES.rst and these are internal message-format fixes that don't change user-visible behavior, so I have not added a fragment. Happy to add one if maintainers prefer.
Verification
  • python3 -m pytest tornado/test/netutil_test.py -p no:relaxed -p no:hypothesispytest -> 11 passed, 2 skipped (CaresResolverTest is unrelated, pre-existing failure from a pycares API change; 1 new test added passes).
  • python3 -m pytest tornado/test/httpclient_test.py -p no:relaxed -p no:hypothesispytest -> 1 new test passes; pre-existing test_unsupported_auth_mode still passes.
  • Manual repro: pre-fix bind_unix_socket('/tmp/regular-file') raises ValueError: ('File %s exists and is not a socket', '/tmp/regular-file'); post-fix it raises ValueError: File /tmp/regular-file exists and is not a socket. Same for the auth_mode check on the simple client.

Drafted with Zo Bot; reviewed by HrachShah.

Zo Bot added 2 commits July 5, 2026 12:06
These two raise statements pass extra positional arguments to
`ValueError` but use only the format string as the first argument,
so the result is a tuple of (format_string, arg) instead of the
formatted message. str(exc) then shows the literal format string
rather than the intended text.

Use string formatting to produce a single formatted message, matching
the pattern used everywhere else in the codebase.

Affected paths:
- web.RequestHandler.xsrf_token: unknown xsrf cookie version %d
- WebSocketProtocol13._process_server_headers: unsupported extension %r
bind_unix_socket raised ValueError('File %s exists and is not a socket', file)
and _HTTPConnection.run raised ValueError('unsupported auth_mode %s', mode).
Both pass a literal format string and the value as separate arguments, so
str(exc) renders the tuple repr with the format string and the value tucked
into e.args[1] rather than producing a usable error message. Replace with
the formatted single-argument form so the offending file path or mode name
is actually visible to a user reading the traceback or a log line.

Two regression tests:
- tornado/test/netutil_test.py::TestBindUnixSocket::
  test_existing_non_socket_file_message_includes_path creates a regular file
  where bind_unix_socket expects a socket, captures the leaked fd from the
  error path, and asserts the path and 'exists and is not a socket' appear
  in str(exc) with a single-arg ValueError.
- tornado/test/httpclient_test.py::HTTPClientCommonTestCase::
  test_unsupported_auth_mode_message_format fetches /auth with auth_mode=
  'asdf' against the simple client and asserts the 'asdf' literal appears in
  the raised ValueError and '%s' does not.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant