You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(multipart): omit nil header string values and handle null objects in write_object_value - #833
Omit None string header values: In multipart serialization, write_str_value(key, value) previously emitted bare header names like Content-Type\r\n (without a colon or value) when value is None. Calling write_str_value with a None value now safely returns without writing malformed header lines, matching MIME header formatting specifications.
Handle null objects in write_object_value: When value is None, write_object_value previously raised ValueError: Expected a MultipartBody instance but got <class 'NoneType'>. It now safely returns early without throwing, establishing behavioral consistency across Kiota serialization writers.
Reverted additional_values_to_merge & Boundary Rewriting: Per maintainer feedback (aligning with microsoft/kiota-serialization-multipart-go#125 and microsoft/kiota-java#2220), multi-body merging and boundary rewriting were reverted in write_object_value. Multipart payloads represent distinct MIME documents with isolated boundaries rather than intersection wrappers.
Verification
Unit tests in packages/serialization/multipart/tests covering:
Header formatting with None string values.
Calling write_object_value with None (ensuring no exception is thrown).
Calling write_object_value with None primary and additional values (ensuring no exception is thrown).
All unit tests passing: 17 passed in packages/serialization/multipart/tests.
Static typing and code style verified with mypy (strict), isort, yapf, and pylint (10.00/10).
This PR brings MultipartSerializationWriter into behavioral alignment with Kiota's other serialization implementations and multipart specifications.
Header formatting:write_str_value(key, value) previously emitted a bare key string (Content-Type\r\n) without a delimiter or value when value was None. It now safely omits empty values, preventing malformed multipart part headers.
Null object safety:write_object_value(key, value) previously raised a ValueError when passed value=None without additional values. It now returns early without throwing.
Intersection wrapper support: Added support for additional_values_to_merge, validating each entry as MultipartBody, writing them sequentially, and properly triggering on_after_object_serialization.
All 18 unit tests in packages/serialization/multipart/tests are passing. Formatting and lint checks (yapf, isort, mypy, and pylint with a score of 10.00/10) have also been verified locally.
I've updated the PR to address the review feedback regarding multipart intersection serialization:
Single Boundary Aggregation: MultipartSerializationWriter.write_object_value now serializes all parts from value and additional_values_to_merge under the primary body's boundary, with a single closing boundary delimiter (--<boundary>--) emitted only after all bodies are processed. This ensures standard MIME parsers process all parts rather than treating trailing bodies as ignored epilogue data.
Preserved Lifecycle Callbacks: The per-object serialization hooks (on_before_object_serialization, on_start_object_serialization, and on_after_object_serialization) continue to execute sequentially for each individual model object.
MIME Parser Verification: Updated the merge test suite to validate that all parts across merged bodies are fully discoverable and extractable using Python's standard email.message_from_bytes MIME parser.
Validation: All tests, static type checks (mypy), code formatting (yapf, isort), and linting (pylint 10.00/10) pass cleanly across 4 signed-off commits.
I've pushed an update addressing the review feedback on serialization lifecycle callback sequencing for merged multipart bodies.
In write_object_value, on_before_object_serialization and on_start_object_serialization are now invoked prior to validating the adapter and parts state, matching the single-body serialization lifecycle order.
Added regression test test_write_object_value_with_additional_values_callback_initialization to cover callback-initialized bodies during merge serialization. All unit tests (19 passed), static typing (mypy), formatting (yapf, isort), and linting (pylint 10.00/10) pass cleanly.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Multipart serialization silently skips invalid falsy additions when the primary body is absent and can emit a stale delimiter when callbacks initialize the boundary.
No open issues 🎉
2 previously missed issues
In code that hasn't changed since last review
Validate falsy additional values when primary value is None
When the primary value is None, any() treats non-None falsy additions such as False, 0, or "" as absent and returns before type validation. These inputs therefore succeed silently, whereas the same invalid additions raise ValueError when a primary body is present. Check explicitly for None so every non-None additional value reaches validation.
The boundary is captured before the primary body's before/start callbacks run. If a callback initializes body.boundary, merged output still uses the old delimiter, so parsing with the updated boundary fails. Capture the boundary after the primary body's callbacks, then retain it for the remaining bodies.
I've addressed the edge cases highlighted by Copilot's review in f8e24d4:
Falsy additional values validation: Updated write_object_value to check not any(v is not None for v in additional_values_to_merge) instead of relying on any()'s truthiness check when the primary value is None. This guarantees that falsy non-None inputs (such as "", 0, or False) are properly validated and raise ValueError consistently with the primary body path.
Boundary capture after callbacks: In merged multipart serialization, the boundary delimiter is now captured from the primary body after its on_before_object_serialization and on_start_object_serialization lifecycle callbacks have executed. This prevents emitting stale boundary delimiters if a callback initializes or modifies body.boundary.
Unit test coverage: Added unit tests in test_multipart_serialization_writer.py verifying falsy invalid additional values, None handling, and boundary updates during callback lifecycle execution. All tests pass cleanly.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Human assessment is needed to judge whether string-only merge tests provide sufficient confidence in model, binary, and filename handling on the untested multi-body path.
Hardik K (hardikkaurani)
changed the title
fix(multipart): omit nil header string values and support additional_values_to_merge
fix(multipart): omit nil header string values and handle null objects in write_object_value
Oct 28, 2026
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Multipart serialization ignores additional_values_to_merge, silently dropping additional bodies, accepting invalid additional values, and producing no output when only an additional body is supplied.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of Changes
write_str_value(key, value)previously emitted bare header names likeContent-Type\r\n(without a colon or value) whenvalue is None. Callingwrite_str_valuewith aNonevalue now safely returns without writing malformed header lines, matching MIME header formatting specifications.write_object_value: Whenvalue is None,write_object_valuepreviously raisedValueError: Expected a MultipartBody instance but got <class 'NoneType'>. It now safely returns early without throwing, establishing behavioral consistency across Kiota serialization writers.additional_values_to_merge& Boundary Rewriting: Per maintainer feedback (aligning withmicrosoft/kiota-serialization-multipart-go#125andmicrosoft/kiota-java#2220), multi-body merging and boundary rewriting were reverted inwrite_object_value. Multipart payloads represent distinct MIME documents with isolated boundaries rather than intersection wrappers.Verification
packages/serialization/multipart/testscovering:Nonestring values.write_object_valuewithNone(ensuring no exception is thrown).write_object_valuewithNoneprimary and additional values (ensuring no exception is thrown).packages/serialization/multipart/tests.mypy(strict),isort,yapf, andpylint(10.00/10).