Fix the error shown when Duo group settings fail to save

What does this MR do and why?

When a save fails on the group GitLab Duo settings page, the alert reads "An error occurred while retrieving your settings. Reload the page to try again." Nothing is retrieved on that path, because the only request is the PUT that just failed. The server's field-level message is handed to captureError and then dropped, so an owner cannot tell which setting was rejected.

This rewords the message for a save and appends the server's field-level messages when the response carries a validation hash, so the alert names the setting. Fields are named by their existing translated label, and a field with no label is omitted, following formatServerValidations in targeted_message_form.vue. Sentry still receives the full error.

locale/gitlab.pot is regenerated in the same commit.

References

#606282 quotes the string. The 400 that produced it was fixed in 19.3 by !244394 (merged) and !247516 (merged), which stopped the form sending an unchanged locked field and guarded the cascading setters server-side. The message itself was not touched, and a save can still fail: a stale form racing another edit, or a validation this page does not model.

How to reproduce

Captured on a self-managed 19.2.4 instance, before the two fixes above.

  1. As instance admin, open Admin > GitLab Duo > Configuration (/admin/gitlab_duo/configuration), clear Allow external agents, and save. This sets lock_duo_external_agents_enabled on the instance.

  2. As owner of any group, open Settings > General > GitLab Duo, change one unrelated and unlocked control such as Allow custom flows, and save.

  3. PUT /api/v4/groups/:id returns 400. The form submits every Duo availability key, including the locked one it renders as disabled, so the response body is:

    {"message":{"namespace_settings.lock_duo_external_agents_enabled":["cannot be changed because it is locked by an ancestor"]}}
  4. The alert reads "An error occurred while retrieving your settings. Reload the page to try again.", and nothing is saved.

On master the same sequence returns 200, so to see the string there, block the PUT in devtools and save.

Screenshots or screen recordings

Before After
armd-02-error-banner-full after-alert-crop

The after image was captured on a source checkout of this branch with the PUT stubbed to return the 19.2.4 validation body; on master the lock case itself returns 200 because the form sends only changed keys.

How to set up and validate locally

  1. Run the specs for the touched files:

    yarn jest ee/spec/frontend/ai/settings/utils_spec.js \
      ee/spec/frontend/ai/settings/pages/ai_group_settings_spec.js
  2. On a running instance, block the PUT in devtools and save. The alert shows the reworded message with nothing appended.

  3. Make the save return a validation hash for a locked field, either by the reproduction above on 19.2.x or by stubbing the 400. The alert names the setting.

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

AI-Generated Content Disclosure: This MR was prepared with assistance from Claude Code. The output has been reviewed for correctness, the reproduction was verified on a running 19.2.4 instance, and the change was validated with the specs and lint named above.

Edited by Andrew Dunn

Merge request reports

Loading
Loading