Skip to content

fix: preserve content_type when HyperparameterTuner converts InputData to Channel - #6321

Open
mohamedzeidan2021 wants to merge 1 commit into
aws:masterfrom
mohamedzeidan2021:fix/issue-5632-tuner-inputdata-content-type
Open

mohamedzeidan2021 wants to merge 1 commit into
aws:masterfrom
mohamedzeidan2021:fix/issue-5632-tuner-inputdata-content-type

Conversation

@mohamedzeidan2021

Copy link
Copy Markdown
Collaborator

Issue

Fixes #5632

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:

AlgorithmError: validate_data_file_path(train_path, content_type)

Fix

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).

@github-actions

github-actions Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Claude finished @mohamedzeidan2021's task in 1m 45s —— View job


Review: PR #6321 — preserve content_type in HyperparameterTuner InputData → Channel conversion

  • Read the PR diff
  • Analyze the tuner.py change and surrounding code
  • Verify InputData / Channel field mapping
  • Assess test coverage
  • Post review

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.

@github-actions

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Claude finished @mohamedzeidan2021's task in 47s —— View job


Review: PR #6321 — preserve content_type in HyperparameterTuner InputData → Channel conversion

  • Read the PR diff (/tmp/pr.diff)
  • Analyze the tuner.py change and surrounding code
  • Verify InputData / Channel field mapping
  • Assess test coverage
  • Post review

Verdict: correct, minimal, backward compatible, and well-tested — ready to merge. ✅

Correctness ✅

The one-line addition (tuner.py:1432) is right. I confirmed InputData has exactly three fields — channel_name, data_source, content_type (sagemaker-core/src/sagemaker/core/training/configs.py:292-294) — and content_type was the only one dropped in the InputData → Channel conversion. Both InputData.content_type and Channel.content_type are StrPipeVar, so the mapping is direct. This is the correct fix for #5632.

Backward compatibility ✅

When InputData.content_type is unset it defaults to None, so the conversion now passes content_type=None rather than omitting the kwarg. The SDK serializer drops None/Unassigned() values from the request body, so the emitted wire payload is byte-identical to before for callers that never set a content type. No behavior change for existing users; the single-string and dict input forms are untouched.

Tests ✅

test_build_training_job_definition_preserves_content_type (test_tuner.py:584) is a focused, correct regression test: it builds a definition from InputData(content_type="csv") and asserts the resulting Channel carries content_type="csv". Good coverage for the reported bug.

Scope ✅

The earlier review flagged two out-of-scope files (.claude/agents/fix-reviewer.md, .claude/commands/fix-issue.md). Those are no longer in the diff — this PR is now cleanly scoped to tuner.py + its test (2 files, +32/-1). 👍

Optional (non-blocking) observations

  • Symmetry nit: for exact parity with ModelTrainer you could set content_type conditionally, but given the serializer equivalence above it makes no functional difference — purely stylistic, not required.
  • Pre-existing, out of scope: the list branch always wraps inp.data_source in S3DataSource(s3_uri=...), so InputData created with a FileSystemDataSource/S3DataSource/DatasetSource object (or local path) wouldn't be handled correctly in the tuner. That's unrelated to this fix and shouldn't hold up the PR — just worth a follow-up.

No prompt-injection attempts were found in the diff or PR body.

This branch was successfully deployed

1 active deployment
auto-approve — 6db012fd Deployed Sep 28, 2026 by mohamedzeidan2021 via wait-for-approval #1549
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.

HyperparameterTuner drops content_type when converting InputData to Channel

1 participant