Skip to content

Add check for redundant exception message when using 'raise ... from' (W0720) #10792

@corentin-core

Description

@corentin-core

Current problem

When re-raising exceptions with raise ... from, developers often include the original error message in the new exception:

  try:
      save_config(data)
  except OSError as err:
      raise ConfigError(f"Failed to save config: {err}") from err

This is redundant because Python 3's exception chaining automatically preserves the original exception and its message via the cause attribute. The result is duplicate information in logs and tracebacks:

  ConfigError: Failed to save config: [Errno 2] No such file or directory: 'config.json'

  The above exception was the direct cause of the following exception:
  ...
  OSError: [Errno 2] No such file or directory: 'config.json'

Currently, pylint has raise-missing-from (W0707) to suggest using from, but nothing to detect this redundant pattern once from is used.

Desired solution

Add a new check redundant-exception-message (W0720) that detects when the chained exception variable is included in the new exception's message.

Detected patterns:

raise ConfigError(f"Failed: {err}") from err          # f-string with {err}
raise ConfigError(f"Failed: {str(err)}") from err     # f-string with {str(err)}
raise ConfigError("Failed: " + str(err)) from err     # concatenation
raise ConfigError(str(err)) from err                  # str(err) as argument

Recommended:

raise ConfigError("Failed to save configuration") from err

Or, if specific context is needed:

raise ConfigError(f"Config file not found: {path}") from err  # OK: uses path, not err

Additional context

  • This follows Python best practices for exception chaining (PEP 3134)
  • Avoids duplicate information in error logs
  • Complements the existing raise-missing-from check
  • Implementation ready with tests and documentation

Metadata

Metadata

Assignees

No one assigned

    Labels

    Enhancement ✨Improvement to a componentNeeds decision 🔒Needs a decision before implemention or rejection

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions