Skip to content

Populate Python API error messages during deserialization - #8010

Open
AayushP123 wants to merge 1 commit into
microsoft:mainfrom
AayushP123:agent/fix-7542-python-primary-error-message
Open

Populate Python API error messages during deserialization#8010
AayushP123 wants to merge 1 commit into
microsoft:mainfrom
AayushP123:agent/fix-7542-python-primary-error-message

Conversation

@AayushP123

@AayushP123 AayushP123 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #7542.

Populates the inherited Python APIError.message field when a generated error property is marked with x-ms-primary-error-message. The property itself was already deserialized, but the exception message remained unset.

Changes

  • Emit a named deserializer for primary error message properties.
  • Assign the parsed value to the generated property and populate APIError.message with an explicit None check and string coercion.
  • Escape generated property-name literals used by setattr.
  • Add a focused Python writer regression test and changelog entry.

Testing

  • Generated the issue's ProblemDetails model and verified the output with python3 -m compileall.
  • dotnet format whitespace kiota.slnx --no-restore --verify-no-changes --include src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs
  • Focused writer tests (2 passed)
  • Non-network builder suite (2,185 passed, 2 skipped); the two anonymous GitHub search tests return HTTP 403 in this environment.

Copilot AI review requested due to automatic review settings August 1, 2026 08:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Not ready to approve

The generated assignment self.message = self.<primary> can propagate None into the exception message; it should coerce None to '' (and update the regression test accordingly) to match existing Python error-message semantics and TypeScript’s ?? "".

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Pull request overview

This PR updates the Python code generator so that when a model is an error type and one of its deserialized properties is marked with x-ms-primary-error-message, the generated deserialization logic also populates the inherited APIError.message field—matching behavior already seen in other languages and fixing #7542.

Changes:

  • Emit a named per-field deserializer function for primary error message properties in Python model get_field_deserializers.
  • In that named deserializer, assign the parsed value to both the generated property and APIError.message.
  • Add a focused Python writer regression test and a changelog entry documenting the fix.
File summaries
File Description
src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs Generates a named deserializer for primary error message properties and wires it into the deserializer map, while setting self.message.
tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs Adds a regression test asserting the new named deserializer and the self.message assignment are emitted.
CHANGELOG.md Documents the Python client behavior change for APIError.message population.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment on lines +580 to +583
writer.StartBlock($"def deserialize_{primaryErrorMessageProperty.Name}(n: ParseNode) -> None:");
writer.WriteLine($"self.{primaryErrorMessageProperty.Name} = n.{GetDeserializationMethodName(primaryErrorMessageProperty.Type, codeElement, parentClass)}");
writer.WriteLine($"self.message = self.{primaryErrorMessageProperty.Name}");
writer.CloseBlock(string.Empty);
Comment on lines +931 to +934
Assert.Contains("def deserialize_detail(n: ParseNode) -> None:", result);
Assert.Contains("self.detail = n.get_str_value()", result);
Assert.Contains("self.message = self.detail", result);
Assert.Contains("\"detail\": deserialize_detail,", result);
@AayushP123
AayushP123 force-pushed the agent/fix-7542-python-primary-error-message branch from cea6f33 to 78bad7b Compare August 1, 2026 09:10
Copilot AI review requested due to automatic review settings August 2, 2026 08:45
@AayushP123
AayushP123 force-pushed the agent/fix-7542-python-primary-error-message branch from 78bad7b to 9efa75f Compare August 2, 2026 08:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Not ready to approve

The new Python writer logic has a correctness issue in how it coerces/assigns APIError.message and also needs escaping when emitting schema-derived property names into single-quoted literals.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (2)

src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs:582

  • APIError.message is assigned using truthiness (or ''), which can silently drop valid falsy values (e.g., 0) and can also assign non-string types if the schema mistakenly marks a non-string property as x-ms-primary-error-message. Using an explicit None check and str(...) keeps the message consistently a string while still coercing None to an empty string.
                writer.StartBlock($"def deserialize_{primaryErrorMessageProperty.Name}(n: ParseNode) -> None:");
                writer.WriteLine($"self.{primaryErrorMessageProperty.Name} = n.{GetDeserializationMethodName(primaryErrorMessageProperty.Type, codeElement, parentClass)}");
                writer.WriteLine($"self.message = self.{primaryErrorMessageProperty.Name} or ''");

src/Kiota.Builder/Writers/Python/CodeMethodWriter.cs:592

  • The property name is written into a single-quoted Python string literal for setattr(...) without escaping. Even though CodeProperty.Name is schema-derived via conventions, escaping at the emission site avoids literal injection/broken output if a name ever contains ', backslashes, or control characters.
            var deserializer = parentClass.IsErrorDefinition && otherProp.IsPrimaryErrorMessage ?
                $"deserialize_{otherProp.Name}" :
                $"lambda n : setattr(self, '{otherProp.Name}', n.{GetDeserializationMethodName(otherProp.Type, codeElement, parentClass)})";
            writer.WriteLine($"\"{otherProp.WireName.SanitizeDoubleQuote()}\": {deserializer},");
  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Copilot AI review requested due to automatic review settings August 3, 2026 09:40
@AayushP123
AayushP123 force-pushed the agent/fix-7542-python-primary-error-message branch from 9efa75f to 83a6536 Compare August 3, 2026 09:40
@AayushP123
AayushP123 marked this pull request as ready for review August 3, 2026 09:40
@AayushP123
AayushP123 requested a review from a team as a code owner August 3, 2026 09:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Not ready to approve

The Python writer currently interpolates schema-derived property names into Python identifier/attribute contexts for the named deserializer path without robust hardening, which can produce invalid code and presents a generated-source injection risk.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (1)

tests/Kiota.Builder.Tests/Writers/Python/CodeMethodWriterTests.cs:915

  • The new primary-error-message deserializer test only covers a simple identifier name (detail). Since the writer now emits a named deserializer, it would be good to add a regression assertion using a hostile/irregular property name (e.g., containing ' and \n) to ensure the named-deserializer path is also safe/escaped (similar to the existing EscapesPropertyNamesInDeserializerBody coverage for the lambda path).
    public void WritesPrimaryErrorMessageDeserializer()
    {
        setup();
        parentClass.IsErrorDefinition = true;
        parentClass.AddProperty(new CodeProperty
  • Files reviewed: 3/3 changed files
  • Comments generated: 1
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Comment on lines +578 to +582
foreach (var primaryErrorMessageProperty in customProperties.Where(static x => x.IsPrimaryErrorMessage))
{
writer.StartBlock($"def deserialize_{primaryErrorMessageProperty.Name}(n: ParseNode) -> None:");
writer.WriteLine($"self.{primaryErrorMessageProperty.Name} = n.{GetDeserializationMethodName(primaryErrorMessageProperty.Type, codeElement, parentClass)}");
writer.WriteLine($"self.message = '' if self.{primaryErrorMessageProperty.Name} is None else str(self.{primaryErrorMessageProperty.Name})");
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.

Python codegen models of custom API errors do not map detail onto APIError's message attribute

2 participants