Skip to content

Conversation

@santoshp210-akamai
Copy link
Contributor

@santoshp210-akamai santoshp210-akamai commented Feb 9, 2026

Description 📝

This PR implements error handling for dependent API failures in the CloudPulse Edit Alert feature

Changes 🔄

-Added hasAPIError boolean field to track API errors across the alert form
-Implemented error detection in components that make API calls (notification channels, metric criteria, dimension filters)
-Display warning notice and disable submit button when API errors occur

Scope 🚢

Upon production release, changes in this PR will be visible to:

  • All customers
  • Some customers (e.g. in Beta or Limited Availability)
  • No customers / Not applicable

Target release date 🗓️

Please specify a release date (and environment, if applicable) to guarantee timely review of this PR. If exact date is not known, please approximate and update it as needed.

Preview 📷

Include a screenshot <img src="" /> or video <video src="" /> of the change.

🔒 Use the Mask Sensitive Data setting for security.

💡 For changes requiring multiple steps to validate, prefer a video for clarity.

Before After
edit-form-before.mp4
edit-form-after.mp4

How to test 🧪

Prerequisites

(How to setup test environment)

  • Under Monitor, click on Alerts.
  • Choose an Alert, click on the Action Menu and choose the Edit alert option
  • In the form, try to disable any of the API's the form might use e.g.,(alert-channels, metric-definition, instances, endpoints, regions, )

Reproduction steps

(How to reproduce the issue, if applicable)

  • Verify that the submit button is disabled and Notice component is there for any dependent API failures
  • Verify that on a retry if api is successful, the submit button is enabled and Notice component is not there

Verification steps

(How to verify changes)

  • Verify that for every
Author Checklists

As an Author, to speed up the review process, I considered 🤔

👀 Doing a self review
❔ Our contribution guidelines
🤏 Splitting feature into small PRs
➕ Adding a changeset
🧪 Providing/improving test coverage
🔐 Removing all sensitive information from the code and PR description
🚩 Using a feature flag to protect the release
👣 Providing comprehensive reproduction steps
📑 Providing or updating our documentation
🕛 Scheduling a pair reviewing session
📱 Providing mobile support
♿ Providing accessibility support


  • I have read and considered all applicable items listed above.

As an Author, before moving this PR from Draft to Open, I confirmed ✅

  • All tests and CI checks are passing
  • TypeScript compilation succeeded without errors
  • Code passes all linting rules

@santoshp210-akamai santoshp210-akamai self-assigned this Feb 9, 2026
@santoshp210-akamai santoshp210-akamai marked this pull request as ready for review February 10, 2026 07:01
@santoshp210-akamai santoshp210-akamai requested a review from a team as a code owner February 10, 2026 07:01
Copy link
Contributor

@pmakode-akamai pmakode-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that a Notice appears when blocking related API requests and the Submit button becomes disabled in that case.

However, shouldn't the Submit button be enabled only when there are no dependent API errors and the form has unsaved changes?

⚠️ Currently, the button is enabled even when there are no edits in the form and is only disabled when the related API has errors. This may allow unnecessary submissions without any actual changes.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements form-level handling for dependent API failures in CloudPulse Edit Alert, surfacing a warning and preventing submission when required data cannot be loaded.

Changes:

  • Adds a hasAPIError form field and wires it into dependent-call components to signal API failures.
  • Displays a warning Notice and disables submit when hasAPIError is true.
  • Adjusts resources/regions UI loading/error behavior and updates related tests/changeset.

Reviewed changes

Copilot reviewed 25 out of 25 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/manager/src/features/CloudPulse/Alerts/EditAlert/EditAlertDefinition.tsx Watches hasAPIError, shows warning notice, disables submit on API error.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/utilities.ts Omits hasAPIError from payload builds (create/edit).
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/types.ts Adds hasAPIError to form type.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/schemas.ts Adds schema support for hasAPIError.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Resources/CloudPulseModifyAlertResources.tsx Passes an error callback down to resource selector.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Regions/CloudPulseModifyAlertRegions.tsx Passes an error callback down to regions selector.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/NotificationChannels/AddChannelListing.tsx Sets hasAPIError based on notification channels query error.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/MetricCriteria.tsx Sets hasAPIError based on metric definition query error.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/useCleanupStaleValues.ts Skips stale-value cleanup when dependent API is in error state.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/constants.ts Adds handleError callback to dimension filter autocomplete props.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueFieldRenderer.tsx Threads handleError into renderer pipeline.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ValueFieldRenderer.test.tsx Updates test props to include handleError.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ObjectStorageDimensionFilterAutocomplete.tsx Detects dependent API errors and reports via handleError.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/ObjectStorageDimensionFilterAutocomplete.test.tsx Updates test props to include handleError.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/FirewallDimensionFilterAutocomplete.tsx Detects dependent API errors and reports via handleError.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/FirewallDimensionFilterAutocomplete.test.tsx Updates test props to include handleError.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/DimensionFilterAutocomplete.test.tsx Updates test props to include handleError.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/BlockStorageDimensionFilterAutocomplete.tsx Detects dependent API errors, reports via handleError, and prevents stale cleanup on error.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterValue/BlockStorageDimensionFilterAutocomplete.test.tsx Updates test props to include handleError.
packages/manager/src/features/CloudPulse/Alerts/CreateAlert/Criteria/DimensionFilterField.tsx Captures child API errors and sets form-level hasAPIError.
packages/manager/src/features/CloudPulse/Alerts/AlertsResources/DisplayAlertResources.tsx Avoids showing empty state when table data has loading error.
packages/manager/src/features/CloudPulse/Alerts/AlertsResources/AlertsResources.tsx Reports resource/region API errors upward and changes loading UI to hide content via display: none.
packages/manager/src/features/CloudPulse/Alerts/AlertsResources/AlertsResources.test.tsx Updates loading-state visibility assertions.
packages/manager/src/features/CloudPulse/Alerts/AlertRegions/AlertRegions.tsx Reports region/resource API errors upward via setError.
packages/manager/.changeset/pr-13379-fixed-1770618987460.md Adds changeset entry describing the fix.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +61 to +63
React.useEffect(() => {
setValue('hasAPIError', notificationChannelsError);
}, [setValue, notificationChannelsError]);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hasAPIError is being overwritten by a single dependency’s error state. If multiple dependent APIs can error, a later effect that sets false will clear the global flag even while other sections are still failing. Consider tracking per-section error flags (e.g., apiErrors.notificationChannels, apiErrors.metricDefinitions, etc.) and deriving hasAPIError = Object.values(apiErrors).some(Boolean), or otherwise aggregating errors so the form only clears the global flag when all dependent APIs are healthy.

Copilot uses AI. Check for mistakes.

export const alertDefinitionFormSchema = createAlertDefinitionSchema.concat(
object({
hasAPIError: mixed<boolean>().optional(),
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mixed<boolean>() doesn’t strictly validate boolean inputs in the way boolean() does (it can allow coercions/values you may not intend). Prefer using boolean().optional() (or mixed().oneOf([true, false]).optional() if you explicitly want that behavior) to keep the schema consistent and stricter.

Copilot uses AI. Check for mistakes.
Comment on lines +217 to +222
React.useEffect(() => {
const hasError = isResourcesError || isRegionsError;
if (setError) {
setError(hasError);
}
}, [setError, isResourcesError, isRegionsError]);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This callback reports only this component’s error state upward. If multiple children call setError/handleError independently, the last writer wins and can incorrectly clear the parent’s global error flag while another dependent API is still failing. Update the parent/consumer contract to support aggregation (e.g., setError(sourceKey, hasError) or setApiErrors((prev) => ({...prev, [sourceKey]: hasError}))), then compute the final hasAPIError from the aggregate.

Copilot uses AI. Check for mistakes.
/**
* Callback triggered when a dependent API has an error.
*/
handleError?: (hasError: boolean) => void;
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error callback is named inconsistently across the diff (handleError in dimension filter components vs setError in regions/resources). Consider standardizing on a single convention (e.g., onApiErrorChange or onDependentApiErrorChange) to make intent and directionality consistent and reduce confusion for component consumers.

Suggested change
handleError?: (hasError: boolean) => void;
onDependentApiErrorChange?: (hasError: boolean) => void;

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +60
React.useEffect(() => {
const hasError = isError || isRegionsError;
if (handleError) {
handleError(hasError);
}
}, [isError, isRegionsError, handleError]);
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behavior is introduced to notify the parent via handleError, but the updated tests only pass a mock function without asserting it’s called with the correct values. Add unit tests that mock useObjectStorageFetchOptions / useRegionsQuery into error and non-error states and assert handleError(true) and handleError(false) are emitted appropriately.

Copilot uses AI. Check for mistakes.
Comment on lines 90 to 91
expect(queryByText(searchPlaceholder)).not.toBeVisible();
expect(queryByText(regionPlaceholder)).not.toBeVisible();
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toBeVisible() expects an HTMLElement; if queryByText(...) returns null, this assertion will error and make the test brittle. If the intent is to assert the element exists but is hidden, use getByText(...) with .not.toBeVisible(). If the intent is to assert it is not rendered, keep .not.toBeInTheDocument().

Suggested change
expect(queryByText(searchPlaceholder)).not.toBeVisible();
expect(queryByText(regionPlaceholder)).not.toBeVisible();
expect(queryByText(searchPlaceholder)).not.toBeInTheDocument();
expect(queryByText(regionPlaceholder)).not.toBeInTheDocument();

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@santoshp210-akamai Could we address this?

@santoshp210-akamai
Copy link
Contributor Author

I see that a Notice appears when blocking related API requests and the Submit button becomes disabled in that case.

However, shouldn't the Submit button be enabled only when there are no dependent API errors and the form has unsaved changes?

⚠️ Currently, the button is enabled even when there are no edits in the form and is only disabled when the related API has errors. This may allow unnecessary submissions without any actual changes.

@pmakode-akamai ,
The disabled state based on dependent API errors is introduced in this PR. Prior to this change, the Submit button did not have any disabled logic.

The overall enablement behavior (i.e., not tying it to unsaved changes) follows the original UX decision from the initial design discussions, so we’ve kept that consistent and only added the blocking condition for dependent API errors.

If we think the button should also depend on unsaved changes, we can loop in the UX team and confirm the behaviour.

@pmakode-akamai
Copy link
Contributor

If we think the button should also depend on unsaved changes, we can loop in the UX team and confirm the behaviour.

Ideally, the behavior should also depend on unsaved changes, as that's the pattern we've been following across the app and aligns with common UX practices.

Since we're already introducing disabled-state logic for the Submit button in this PR (based on API errors), it might be worth confirming whether unsaved changes should also be included in the enablement logic. We can loop in UX to clarify and address it here if possible, or handle it in a follow-up PR if needed.

Copy link
Contributor

@pmakode-akamai pmakode-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I see the Notice when the related API requests are blocked - that looks good ✅

  • The enablement of the Submit button based on unsaved changes should also be reviewed, either in this PR or in a follow-up ❗️

    • This is important, as keeping the Submit always enabled and disabling it only when a related API fails doesn't seem ideal. In its current state, a user could trigger a Submit action before the dependent APIs have finished loading or before errors are surfaced, which could lead to unintended or redundant requests.
  • Also, there are merge conflicts that need to be resolved ❗️

@santoshp210-akamai
Copy link
Contributor Author

@pmakode-akamai , I have resolved the conflicts.

For the behaviour of enabling the Submit on unsaved changes, we will review with UX and take it as part of a separate PR.

So for now we can proceed with this PR

Copy link
Contributor

@pmakode-akamai pmakode-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving this so that there are no blockers, but we still need to revisit the Submit button in the edit flow.

Apart from that, I think you still need to look into this comment: #13379 (comment)

@github-project-automation github-project-automation bot moved this from Review to Approved in Cloud Manager Feb 12, 2026
@linode-gh-bot
Copy link
Collaborator

Cloud Manager UI test results

🎉 866 passing tests on test run #7 ↗︎

❌ Failing✅ Passing↪️ Skipped🕐 Duration
0 Failing866 Passing11 Skipped44m 59s

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Approved

Development

Successfully merging this pull request may close these issues.

4 participants