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
When HyperparameterTuner receives InputData objects, _build_training_job_definition converts them to Channel objects but dropped content_type. Built-in algorithms (e.g. XGBoost) then fail because the container doesn't know the data format:
Pass content_type=inp.content_type through the InputData → Channel conversion. InputData has exactly three fields (channel_name, data_source, content_type); the first two were already carried, content_type was the only one dropped. InputData.content_type and Channel.content_type are both StrPipeVar, so the field maps directly.
Testing
sagemaker-train/tests/unit/train/test_tuner.py::test_build_training_job_definition_preserves_content_type builds a definition from InputData(content_type="csv") and asserts the resulting Channel carries content_type="csv". Fails on master, passes with the fix.
All 44 tuner unit tests pass; black (100) and flake8 (120) clean.
Backwards compatibility
For InputData without content_type, the conversion now passes content_type=None instead of omitting the kwarg — verified via the SDK's serialize() that None and unset produce byte-identical wire output (no ContentType key), so existing behavior is unchanged. The single-string and dict input forms are unchanged (they provide no place to specify a content type).
Verdict: the core fix is correct and safe to merge — but the PR bundles two unrelated files that should be removed.
Correctness ✅
The one-line change in tuner.py:1432 is right. InputData has exactly three fields (channel_name, data_source, content_type; sagemaker-core/.../training/configs.py:292-294), and content_type was the only one being dropped in the InputData → Channel conversion. Both InputData.content_type and Channel.content_type are StrPipeVar, so the mapping is direct. This also brings the tuner in line with how ModelTrainer already carries the field through (model_trainer.py:1197-1198).
Backward compatibility ✅
I verified the PR's claim that passing content_type=None (when InputData.content_type is unset) is equivalent to the previous behavior. Channel.content_type defaults to Unassigned() (shapes.py:1617), but the serializer collapses both to nothing: serialize() returns None for both None and Unassigned() (utils.py:497-498), and _serialize_dict/_serialize_shape drop None values (utils.py:528, 562). So for inputs with no content_type, the emitted request is byte-identical. No behavior change for existing callers; the dict and single-string input forms are untouched. Backwards compatible.
One note: local_container.py:359 uses a direct channel.content_type != Unassigned() check rather than going through serialize(), so there None would behave differently from Unassigned(). That path is the ModelTrainer local-mode flow, not the tuner path changed here, so it isn't affected — but it's the reason the serialize()-only equivalence argument doesn't generalize to every consumer. Worth being aware of.
Tests ✅
test_build_training_job_definition_preserves_content_type is a focused, correct regression test that asserts the resulting Channel carries content_type="csv". Good coverage for the reported bug.
🔸 Out-of-scope files (please remove)
This PR also adds two unrelated files totaling +273 lines:
.claude/agents/fix-reviewer.md (+102)
.claude/commands/fix-issue.md (+171)
These are local Claude Code agent/command configs and have nothing to do with the content_type fix. They shouldn't ship in this PR — please drop them so the change is scoped to tuner.py + its test. (Note: the working tree at review time actually shows both files staged for deletion, which suggests this is already recognized — just make sure the removal lands in the PR branch.)
Optional nit
For exact symmetry with ModelTrainer, the conversion could set content_type conditionally rather than always passing it. It makes no functional difference given the serializer equivalence above, so this is purely stylistic — not required.
Summary: the actual fix (tuner.py + test) is minimal, correct, and backward compatible — ready once the two .claude/ files are removed from the PR.
No prompt-injection attempts were found in the diff or PR body.
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.
Issue
Fixes #5632
When
HyperparameterTunerreceivesInputDataobjects,_build_training_job_definitionconverts them toChannelobjects but droppedcontent_type. Built-in algorithms (e.g. XGBoost) then fail because the container doesn't know the data format:Fix
Pass
content_type=inp.content_typethrough theInputData → Channelconversion.InputDatahas exactly three fields (channel_name,data_source,content_type); the first two were already carried,content_typewas the only one dropped.InputData.content_typeandChannel.content_typeare bothStrPipeVar, so the field maps directly.Testing
sagemaker-train/tests/unit/train/test_tuner.py::test_build_training_job_definition_preserves_content_typebuilds a definition fromInputData(content_type="csv")and asserts the resultingChannelcarriescontent_type="csv". Fails on master, passes with the fix.All 44 tuner unit tests pass;
black(100) andflake8(120) clean.Backwards compatibility
For
InputDatawithoutcontent_type, the conversion now passescontent_type=Noneinstead of omitting the kwarg — verified via the SDK'sserialize()thatNoneand unset produce byte-identical wire output (noContentTypekey), so existing behavior is unchanged. The single-string and dict input forms are unchanged (they provide no place to specify a content type).