Skip to content

fix: lead APIError's string form with the error message - #724

Merged
Vincent Biret (baywet) merged 4 commits into
microsoft:mainfrom
HardMax71:fix/api-error-str-leads-with-message
Sep 10, 2026
Merged

fix: lead APIError's string form with the error message#724
Vincent Biret (baywet) merged 4 commits into
microsoft:mainfrom
HardMax71:fix/api-error-str-leads-with-message

Conversation

@HardMax71

@HardMax71 Max Azatian (HardMax71) commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Overview

APIError.__str__ returned a multi-line string that started with a newline and printed message: None for every generated error model, because the generator never sets message; it emits a primary_message property that __str__ ignored. Anything that titles an exception by its first line (Sentry does exactly value.splitlines()[0], most log viewers do the same) showed ODataError: with nothing after it, and logging.error("...: %s", err) printed a blank line followed by an indented block.

primary_message is now a property on APIError that returns message; generated error models already override it with the message from the API's error payload. __str__ reads it (falling back to the class name) and appends the status code in parentheses. There is no getattr lookup any more, and the nested error: payload line is gone with it; a generated model can render its payload in its own __str__ if wanted. For the throttling example from the issue:

Application is over its MailboxConcurrency limit. (status 429)

This matches the dotnet abstraction, where the generated error overrides Message with Error?.Message; Python cannot override the message dataclass field with a property, so the override lives on primary_message.

Related Issue

Fixes #723

Notes

The getattr(self, "error", None) guard from #133 is removed; __str__ no longer reaches into subclass fields.

Testing Instructions

  • cd packages/abstractions && pytest tests/test_api_error.py: a bare message, the status suffix, the class-name fallback, primary_message defaulting to message, a generated-style subclass overriding primary_message, and that no variant starts with a blank line.
  • The whole abstractions suite: 139 passed. yapf, isort and mypy clean; pylint reports only the pre-existing .pylintrc option warnings.

str(APIError) started with a newline and printed message: None for every generated error model, ignoring the primary_message the generator emits, so any log line or error title built from the first line was empty. The first line now carries the message (primary_message, then message, then the class name), the status code and the error code; the nested error payload follows on a second line.
@HardMax71
Max Azatian (HardMax71) requested a review from a team as a code owner September 7, 2026 14:22
Copilot AI lite review requested due to automatic review settings September 7, 2026 14:22

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The formatting change is localized, matches the stated issue/expected behavior, and is covered by targeted new tests for the key scenarios.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@baywet Vincent Biret (baywet) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution!

Comment thread packages/abstractions/kiota_abstractions/api_error.py Outdated
The base class has no notion of an error code; `error.code` is the OData
error contract as Graph exposes it. The first line is now the message and
the status only, the code stays visible on the error line.
Comment thread packages/abstractions/kiota_abstractions/api_error.py Outdated
…tattr lookups

primary_message is a real property on the base class, returning message,
that generated error models override; __str__ reads it plus the status
code and no longer looks up error or primary_message by name.
@sonarqubecloud

Copy link
Copy Markdown

@baywet Vincent Biret (baywet) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for making the changes!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The change is narrowly scoped to APIError.__str__, aligns with the stated issue/intent, and includes targeted regression tests for the key behaviors.

Review details
  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

@baywet
Vincent Biret (baywet) merged commit b306b55 into microsoft:main Sep 10, 2026
53 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress 🚧 to Done ✔️ in Kiota Sep 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done ✔️

Development

Successfully merging this pull request may close these issues.

APIError.__str__ starts with a newline and ignores the generated primary_message, so every error is titled "ODataError:" with nothing after it

3 participants