fix(core): recognize new duplicate-name error wording; add actionable train() errors - #6256
fix(core): recognize new duplicate-name error wording; add actionable train() errors#6256jam-jee wants to merge 1 commit into
Conversation
…rrors Telemetry shows the single largest V3 failure signature (40% of all failures, 465 accounts over 90 days) is CreatePipeline/CreateExperiment rejecting duplicate names. The service changed its error wording from '... already exists' to '... names must be unique within an AWS account ...', which silently broke every load-or-create flow that matched the old substring: Pipeline.upsert, Experiment/_Trial/ _TrialComponent._load_or_create, and _create_resource re-raised instead of loading or updating the existing resource. - Add a shared _is_resource_already_exists_error predicate in common_utils that matches all known wordings and error codes, and use it at all five call sites. - Pipeline.create: on a name collision, log guidance pointing at upsert() before re-raising. - ModelTrainer.train: log actionable remediation for terminal CreateTrainingJob failures before re-raising unchanged -- ResourceLimitExceeded (57% of ModelTrainer failures; quota name + Service Quotas link, flags that retries cannot succeed), AccessDenied (PassRole hint), NoRegionError and NoCredentialsError (setup steps). All error paths re-raise the original exception; only logging is added, so no caller contract changes. --- X-AI-Prompt: implement error-pattern action items from PySDK telemetry deep dive X-AI-Tool: Kiro
|
Claude finished @jam-jee's task in 1m 33s —— View job PR Review: fix(core): duplicate-name error wording + actionable train() errors
Overall this is a well-scoped, well-tested fix. The root-cause framing (service changed duplicate-name wording, five call sites matched the old substring) is accurate, the shared predicate consolidates the duplicated logic nicely, and every path preserves the original exception contract (re-raises unchanged). Test coverage is thorough and pins both old and new wordings. No blocking issues found. A few observations, none blocking: 1. 2. The 3. 4. Minor: Security / correctness: No credential handling concerns — the new logging only echoes error codes/messages already returned by the service and static remediation text (no secrets). The Tests: Coverage is strong — predicate pinned against both wordings + Note: the inline-comment tool wasn't available in this environment, so this feedback is consolidated here rather than posted as line comments. |
Problem
SDK telemetry shows the single largest V3 failure signature (about 40% of all recorded V3 failures over the last 90 days) is
CreatePipeline/CreateExperimentrejecting duplicate names, even for callers usingpipeline.upsert()which is supposed to handle exactly this case. Separately,ModelTrainer.train()failures are dominated by terminal service errors (ResourceLimitExceededalone is 57% of them) that surface as raw botocore exceptions with no remediation guidance, which drives blind retry loops that cannot succeed.Why it matters
upsert()and every load-or-create flow in the SDK are silently broken for the affected resource types: instead of loading or updating the existing resource, they re-raise, breaking documented create-or-update workflows (repeated CI/CD pipeline deployments, experiment runs).Fix (symptom -> root cause -> change)
Symptom:
upsert()raisesValidationExceptionon an existing pipeline. Root cause: the SageMaker service changed its duplicate-name error wording from... already existsto... names must be unique within an AWS account ..., and five separate call sites detect "resource already exists" by matching the old"already exists"substring:Pipeline.upsert,Experiment._load_or_create,_Trial._load_or_create,_TrialComponent._load_or_create, andcommon_utils._create_resource. All five stopped recognizing the collision and re-raised.Changes:
_is_resource_already_exists_error()insagemaker-core/common_utils.pymatching all known wordings (already exists,Cannot create already existing,must be unique within an AWS account) and codes (ValidationException,ResourceInUse). The uniqueness pattern is deliberately scoped withwithin an AWS accountso definition-internal uniqueness errors (for example duplicate step names within a pipeline) are not mistaken for a name collision. All five call sites now use it.Pipeline.create(): on a name collision, log an ERROR pointing the caller atupsert()before re-raising.upsert()suppresses this hint via a keyword-only_log_name_collision_hint=Falseso the normal create-or-update path stays silent.ModelTrainer.train(): log actionable remediation before re-raising the original exception unchanged:ResourceLimitExceeded(parsed quota name, Service Quotas console link, explicit "retrying will keep failing"),AccessDenied(iam:PassRolehint),NoRegionErrorandNoCredentialsError(setup steps). No exception contract changes anywhere: every path re-raises the original exception.Tests
sagemaker-core/tests/unit/test_common_utils.py: 9 new tests pinning the predicate against both old and new service wordings,ResourceInUse, non-collisionValidationExceptions, and the definition-internal uniqueness negative case (Step names must be unique within a pipelinemust NOT match).sagemaker-core/tests/unit/experiments/test_load_or_create.py(new): load-or-create forExperiment,_Trial,_TrialComponentparameterized over both wordings, plus re-raise of unrelated validation errors.sagemaker-mlops/tests/unit/workflow/test_pipeline_class.py: upsert updates on the new wording; upsert of an existing pipeline emits no ERROR hint; barecreate()collision logs the hint and re-raises.sagemaker-train/tests/unit/train/test_model_trainer.py:ResourceLimitExceeded/NoRegionError/NoCredentialsErrorre-raise with guidance logged;AccessDeniedhint; unrelated codes stay silent.Manual verification
N/A. Unit coverage is sufficient: all changes are message matching and logging around unchanged exception flow, fully exercised by mocked ClientError responses copied verbatim from live service messages observed in SDK telemetry.
Screenshots
N/A, no user-visible UI change (client library).