Skip to content

stdlib: don't clear LogRecord.args before ProcessorFormatter processors run - #810

Closed
SarthakB11 wants to merge 1 commit into
hynek:mainfrom
SarthakB11:fix/issue-771
Closed

SarthakB11 wants to merge 1 commit into
hynek:mainfrom
SarthakB11:fix/issue-771

Conversation

@SarthakB11

Copy link
Copy Markdown

Summary

In the foreign branch of ProcessorFormatter.format(), record.args = () was being assigned before foreign_pre_chain and the main processors chain ran.
Processors that look at event_dict["_record"].args therefore always saw an empty tuple, even when stdlib was called with positional args like logger.info("a=%s b=%s", "a", "b").

The clear is necessary: once record.msg is replaced with the rendered structlog string, leaving non-empty record.args makes logging.Formatter.format() raise TypeError: not all arguments converted during string formatting.
But it only needs to happen after the processor chain.
The fix moves record.args = () to right before record.msg = ed / super().format(record) and leaves a comment so a future refactor doesn't drop it again.

test_clears_args (the regression guard for the original TypeError) and test_pass_foreign_args_true_sets_positional_args_key still pass.
New test_record_args_accessible_in_processor reproduces #771 at the public API surface and asserts the foreign-pre-chain processor sees record.args == ("a", "b").

Closes #771.

Pull Request Check List

  • I acknowledge this project's AI policy.
  • This pull requests is not from my main branch.
  • There's tests for all new and changed code.
  • New APIs are added to our typing tests in api.py.
    • No new APIs.
  • Updated documentation for changed code.
    • New functions/classes have to be added to docs/api.rst by hand.
      • No new public symbols.
    • Changed/added classes/methods/functions have appropriate versionadded, versionchanged, or deprecated directives.
      • Behavior fix; public contract unchanged.
  • Documentation in .rst and .md files is written using semantic newlines.
  • Changes (and possible deprecations) are documented in the changelog.
@hynek

hynek commented May 10, 2026

Copy link
Copy Markdown
Owner

did you run into the problem yourself too, or did you just try to fix #771? I'm not sure why it should be a problem since we pass args inside of event_dict. Futzing around with stdlib integration is a rather risky endeavor.

@hynek

hynek commented May 10, 2026

Copy link
Copy Markdown
Owner

to wit: if I'm not mistaken this patch changes the behavior of getMessage() (now has interpolation).

@SarthakB11

Copy link
Copy Markdown
Author

You're right. With this patch, processors calling record.getMessage() during the chain would see the interpolated message instead of the format string, which is a behavior change. The reporter's case is already covered by pass_foreign_args=True (sets event_dict["positional_args"]). Closing.

@SarthakB11 SarthakB11 closed this May 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants