Skip to content

🤖🤖🤖 r/aws_cognito_user_pool: Fix InvalidParameterException for a partially specified admin_create_user_config.invite_message_template - #49207

Open
timoguin wants to merge 3 commits into
hashicorp:mainfrom
timoguin:b-aws_cognito_user_pool-invite-message-template
Open

🤖🤖🤖 r/aws_cognito_user_pool: Fix InvalidParameterException for a partially specified admin_create_user_config.invite_message_template#49207
timoguin wants to merge 3 commits into
hashicorp:mainfrom
timoguin:b-aws_cognito_user_pool-invite-message-template

Conversation

@timoguin

Copy link
Copy Markdown
Contributor

Rollback Plan

If a change needs to be reverted, we will publish an updated version of the library.

Changes to Security Controls

No.

Description

admin_create_user_config.invite_message_template cannot be partially specified today. All three attributes are documented Optional, but setting any one of them requires setting all three.

expandAdminCreateUserConfigType reads the block from a Plugin SDKv2 nested block map, in which every declared attribute is always present holding its zero value. The if v, ok := tfMap[...]; ok presence checks therefore never fail, so an unset attribute is marshalled as aws.String(""):

if v, ok := tfMap["sms_message"]; ok {
	imt.SMSMessage = aws.String(v.(string))
}

Cognito enforces a minimum length on each field (emailMessage 6, emailSubject 1, sMSMessage 6), so CreateUserPool/UpdateUserPool fail:

InvalidParameterException: 1 validation error detected: Value '' at
'adminCreateUserConfig.inviteMessageTemplate.sMSMessage' failed to satisfy constraint:
Member must have length greater than or equal to 6

The defect is symmetric — an SMS-only template fails on the two email fields the same way.

This guards each assignment on a non-empty value, matching expandVerificationMessageTemplateType in the same file, which already does exactly this for the sibling verification_message_template block.

Why this is safe:

  • Cognito accepts an omitted field. Only a present-and-empty one is rejected. Verified against the real API in us-east-2: CreateUserPool with SMSMessage absent from InviteMessageTemplate succeeds and stores an email-only template, on a pool with no sms_configuration.
  • "" is not a legal value for any of the three. The provider's own validators (validUserPoolInviteTemplateEmailMessage, validUserPoolTemplateEmailSubject, validUserPoolInviteTemplateSMSMessage) enforce the same minimum lengths as the API, so no configuration's intent is "send the empty string" and the guard discards nothing expressible.
  • No perpetual diff. flattenAdminCreateUserConfigType already skips nil fields, so an omitted field reads back as the SDKv2 zero value "" and matches the configuration. Covered by the ImportState/ImportStateVerify steps in the new tests.
  • Note on clearing a previously set field. Removing sms_message from a configuration that had one will not clear it in Cognito. That is pre-existing and unavoidable — sending "" cannot clear it either, since the API rejects ""; clearing requires removing the whole invite_message_template block. The verification_message_template sibling behaves identically today.

A plan-time validator cannot address this: an SDKv2 ValidateFunc does not run on an unset attribute, so the minimum-length validators never fire on this path. Making the attributes Required was also considered and rejected — it would break working configurations that set all three, and would encode an API quirk in the provider's interface rather than fixing the marshalling.

Every existing test sets all three attributes, which is why this survived so long. Added:

  • TestExpandAdminCreateUserConfigType — a unit test over the map shape SDKv2 actually supplies, covering all-fields, email-only, SMS-only, empty and absent templates. This fails on main without AWS credentials.
  • TestAccCognitoIDPUserPool_withAdminCreateUserEmailOnlyInviteMessageTemplate and ..._withAdminCreateUserSMSOnlyInviteMessageTemplate, each with an ImportState/ImportStateVerify step.

The two acceptance tests are deliberately separate rather than two steps of one test: transitioning between email-only and SMS-only cannot clear the previously set fields (see above), so a second step would report a non-empty plan for reasons unrelated to this change.

AI usage disclosure

Per docs/ai-usage.md, this PR was prepared with the assistance of an LLM agent (Claude Code), hence 🤖🤖🤖 in the title.

  • The agent was given the diagnosis and the intended fix — guard the three assignments to match expandVerificationMessageTemplateType — and wrote the guard, the unit test, and the two acceptance tests plus their config builders.
  • It ran the unit test against unfixed and fixed code, and the acceptance tests against real Cognito in us-east-2 both before (reproducing the InvalidParameterException above) and after the change, as well as make build, make test, and make ci-quick.
  • I reviewed every line, verified the reasoning above independently, and am accountable for this code.

Relations

Closes #49203
Relates #13060

References

Output from Acceptance Testing

Before the change (the reported failure, reproduced):

% make testacc PKG=cognitoidp TESTS='TestAccCognitoIDPUserPool_withAdminCreateUser(Email|SMS)OnlyInviteMessageTemplate'

=== NAME  TestAccCognitoIDPUserPool_withAdminCreateUserEmailOnlyInviteMessageTemplate
    user_pool_test.go:242: Step 1/2 error: Error running apply: exit status 1

        Error: creating Cognito User Pool (tf-acc-test-145519881179330092): operation error Cognito Identity Provider: CreateUserPool, https response error StatusCode: 400, RequestID: 0bc96905-e0a9-43db-ab1b-e59010db9c18, InvalidParameterException: 1 validation error detected: Value '' at 'adminCreateUserConfig.inviteMessageTemplate.sMSMessage' failed to satisfy constraint: Member must have length greater than or equal to 6

=== NAME  TestAccCognitoIDPUserPool_withAdminCreateUserSMSOnlyInviteMessageTemplate
    user_pool_test.go:273: Step 1/2 error: Error running apply: exit status 1

        Error: creating Cognito User Pool (tf-acc-test-92831952279861135): operation error Cognito Identity Provider: CreateUserPool, https response error StatusCode: 400, RequestID: 43853e46-9a12-404e-8e42-529d77313c8e, InvalidParameterException: 3 validation errors detected: Value '' at 'adminCreateUserConfig.inviteMessageTemplate.emailMessage' failed to satisfy constraint: Member must have length greater than or equal to 6; Value '' at 'adminCreateUserConfig.inviteMessageTemplate.emailSubject' failed to satisfy constraint: Member must satisfy regular expression pattern: [\p{L}\p{M}\p{S}\p{N}\p{P}\s]+; Value '' at 'adminCreateUserConfig.inviteMessageTemplate.emailSubject' failed to satisfy constraint: Member must have length greater than or equal to 1

--- FAIL: TestAccCognitoIDPUserPool_withAdminCreateUserSMSOnlyInviteMessageTemplate (5.01s)
--- FAIL: TestAccCognitoIDPUserPool_withAdminCreateUserEmailOnlyInviteMessageTemplate (5.02s)
FAIL

After the change, including the previously passing all-fields tests:

% make testacc PKG=cognitoidp TESTS=TestAccCognitoIDPUserPool_withAdminCreateUser

--- PASS: TestAccCognitoIDPUserPool_withAdminCreateUserAndPasswordPolicy (17.66s)
--- PASS: TestAccCognitoIDPUserPool_withAdminCreateUserSMSOnlyInviteMessageTemplate (17.67s)
--- PASS: TestAccCognitoIDPUserPool_withAdminCreateUserEmailOnlyInviteMessageTemplate (17.72s)
--- PASS: TestAccCognitoIDPUserPool_withAdminCreateUser (26.71s)
PASS
ok      github.com/hashicorp/terraform-provider-aws/internal/service/cognitoidp 33.046s

Unit test:

% go test ./internal/service/cognitoidp/ -run TestExpandAdminCreateUserConfigType -v

--- PASS: TestExpandAdminCreateUserConfigType (0.00s)
    --- PASS: TestExpandAdminCreateUserConfigType/all_fields (0.00s)
    --- PASS: TestExpandAdminCreateUserConfigType/empty_invite_message_template (0.00s)
    --- PASS: TestExpandAdminCreateUserConfigType/no_invite_message_template (0.00s)
    --- PASS: TestExpandAdminCreateUserConfigType/email_only (0.00s)
    --- PASS: TestExpandAdminCreateUserConfigType/SMS_only (0.00s)
PASS
ok      github.com/hashicorp/terraform-provider-aws/internal/service/cognitoidp 6.535s

timoguin and others added 2 commits July 30, 2026 11:08
`expandAdminCreateUserConfigType` reads `admin_create_user_config` from a
Terraform Plugin SDKv2 nested block map, in which every declared attribute is
always present holding its zero value. The `ok` presence checks therefore never
fail, and an unset `email_message`, `email_subject`, or `sms_message` was
marshalled as `""`.

Cognito requires a minimum length for each of these (6, 1, and 6 respectively),
so `CreateUserPool` and `UpdateUserPool` fail with `InvalidParameterException`
whenever the block is partially specified, even though all three attributes are
Optional. An omitted field is accepted; only a present-and-empty one is not.

Guard each assignment on a non-empty value, matching
`expandVerificationMessageTemplateType` in the same file, which already does
this for the sibling `verification_message_template` block. `""` is not a legal
value for any of the three, so nothing expressible is discarded, and
`flattenAdminCreateUserConfigType` already skips nil fields, so an omitted
field reads back as `""` and matches the configuration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…mplate`

Every existing test sets all three `invite_message_template` attributes, so the
partially specified case had no coverage.

Add `TestExpandAdminCreateUserConfigType`, covering email-only, SMS-only, empty
and absent templates, plus acceptance tests for email-only and SMS-only invite
templates with `ImportState`/`ImportStateVerify` steps.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@timoguin
timoguin requested a review from a team as a code owner July 30, 2026 16:14
@dosubot dosubot Bot added the bug Addresses a defect in current functionality. label Jul 30, 2026
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

✅ Thank you for correcting the previously detected issues! The maintainers appreciate your efforts to make the review process as smooth as possible.

@github-actions

Copy link
Copy Markdown
Contributor

Community Guidelines

This comment is added to every new Pull Request to provide quick reference to how the Terraform AWS Provider is maintained. Please review the information below, and thank you for contributing to the community that keeps the provider thriving! 🚀

Voting for Prioritization

  • Please vote on this Pull Request by adding a 👍 reaction to the original post to help the community and maintainers prioritize it.
  • Please see our prioritization guide for additional information on how the maintainers handle prioritization.
  • Please do not leave +1 or other comments that do not add relevant new information or questions; they generate extra noise for others following the Pull Request and do not help prioritize the request.

Pull Request Authors

  • Review the contribution guide relating to the type of change you are making to ensure all of the necessary steps have been taken.
  • Whether or not the branch has been rebased will not impact prioritization, but doing so is always a welcome surprise.

@github-actions github-actions Bot added needs-triage Waiting for first response or review from a maintainer. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure. service/cognitoidp Issues and PRs that pertain to the cognitoidp service. size/L Managed by automation to categorize the size of a PR. labels Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Addresses a defect in current functionality. needs-triage Waiting for first response or review from a maintainer. service/cognitoidp Issues and PRs that pertain to the cognitoidp service. size/L Managed by automation to categorize the size of a PR. tests PRs: expanded test coverage. Issues: expanded coverage, enhancements to test infrastructure.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: aws_cognito_user_pool sends an empty InviteMessageTemplate.SMSMessage, making the documented-Optional sms_message effectively required

1 participant