Skip to content

Commit 59f225e

Browse files
authored
Display server errors in modals, don't use toasts (#3192)
Found this while working on #3178. Instance resize, attach floating IP, and attach ephemeral IP all had `onError`s that triggered toasts on server error. The first two also displayed the error in the modal. Ephemeral IP did not. This PR gets rid of the toasts and puts an error display into attach ephemeral IP. It doesn't look very good (maybe we should move the error and give it a little box or something), but it's basically the same as it already was, minus the extra toasts. (Screenshot is from playwright, hence the weird missing submit button — I think it's right in the middle of switching between the button text and the loading spinner.) <img width="930" height="528" alt="Screenshot 2026-04-21 at 5 20 23 PM" src="https://github.com/user-attachments/assets/0c6db6a6-913f-40aa-8ccc-245be9dfc1d0" />
1 parent f25398d commit 59f225e

4 files changed

Lines changed: 6 additions & 15 deletions

File tree

app/components/AttachEphemeralIpModal.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,6 @@ export const AttachEphemeralIpModal = ({
6565
addToast(<>IP <HL>{ephemeralIp.ip}</HL> attached</>)
6666
onDismiss()
6767
},
68-
onError: (err) => {
69-
addToast({ title: 'Error', content: err.message, variant: 'error' })
70-
},
7168
})
7269

7370
const form = useForm({ defaultValues: { pool: defaultPool } })
@@ -96,6 +93,9 @@ export const AttachEphemeralIpModal = ({
9693
noItemsPlaceholder="No pools available"
9794
/>
9895
</form>
96+
{instanceEphemeralIpAttach.error && (
97+
<p className="text-error mt-4">{instanceEphemeralIpAttach.error.message}</p>
98+
)}
9999
</Modal.Section>
100100
</Modal.Body>
101101
<Modal.Footer

app/components/AttachFloatingIpModal.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,6 @@ export const AttachFloatingIpModal = ({
8585
addToast(<>IP <HL>{floatingIp.name}</HL> attached</>)
8686
onDismiss()
8787
},
88-
onError: (err) => {
89-
addToast({ title: 'Error', content: err.message, variant: 'error' })
90-
},
9188
})
9289
const form = useForm({ defaultValues: { floatingIp: '' } })
9390
const floatingIp = form.watch('floatingIp')

app/pages/project/instances/InstancePage.tsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -301,9 +301,6 @@ export function ResizeInstanceModal({
301301
: undefined, // Only link to the instance if we're not already on that page
302302
})
303303
},
304-
onError: (err) => {
305-
addToast({ title: 'Error', content: err.message, variant: 'error' })
306-
},
307304
})
308305

309306
const form = useForm({

test/e2e/instance.e2e.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,13 +218,10 @@ test('resize modal stays open on server error', async ({ page }) => {
218218
await resizeModal.getByRole('textbox', { name: 'Memory' }).fill('20')
219219
await resizeModal.getByRole('button', { name: 'Resize' }).click()
220220

221-
// Wait for the error toast, which confirms the mutation has completed
222-
await expect(page.getByTestId('Toasts')).toContainText('Cannot update instance')
223-
224-
// Modal should stay open so the user can see the error and adjust values
221+
// Error renders inline inside the modal; modal stays open so the user can
222+
// see the error and adjust values.
223+
await expect(resizeModal).toContainText('Cannot update instance')
225224
await expect(resizeModal).toBeVisible()
226-
227-
await closeToast(page)
228225
})
229226

230227
test('delete from instance detail', async ({ page }) => {

0 commit comments

Comments
 (0)