Skip to content

fix: improve import error UX with server-reachability probe#24

Open
damienriehl wants to merge 1 commit intomainfrom
fix/import-error-handling
Open

fix: improve import error UX with server-reachability probe#24
damienriehl wants to merge 1 commit intomainfrom
fix/import-error-handling

Conversation

@damienriehl
Copy link
Contributor

@damienriehl damienriehl commented Mar 19, 2026

Summary

  • XHR error handler now probes the API root before reporting — distinguishes "server down" from "server returned a CORS-blocked error" (e.g. unhandled 500 without CORS headers)
  • 5-minute timeout added for large file uploads (was unlimited)
  • Error banner moved out of FileUpload component into a dedicated alert with icon, so the file selection doesn't look invalid
  • Error cleared when user selects a new file

Context

Importing an 18MB OWL file showed "Could not reach the server" even though the server was running — the actual cause was a 500 from a missing DB migration whose response lacked CORS headers, triggering the XHR error event instead of load.

Test plan

  • Import a valid ontology file — should upload and redirect to the new project
  • Stop the API server, try import — should show "Could not reach the server"
  • Trigger a server 500 on import — should show "The server encountered an error..."
  • Select a new file after an error — error banner should clear

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added 5-minute timeout protection for file uploads.
    • Improved error messaging to distinguish between network connectivity failures and server unavailability.
  • Bug Fixes

    • Enhanced error handling to prevent unhandled exceptions during file import.
    • Errors now clear when selecting a new file.
    • Error messages display in a dedicated alert panel for better visibility.

- Add 5-min XHR timeout for large file uploads
- Probe API root on XHR error to distinguish "server down" from
  "server returned error without CORS headers" (e.g. unhandled 500)
- Move import error out of FileUpload into a separate alert banner
- Clear import error when user selects a new file

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 19, 2026

📝 Walkthrough

Walkthrough

File upload error handling was enhanced with timeout detection and improved network diagnostics. The project creation page's error display was refactored to show errors in a dedicated alert panel instead of through the FileUpload component prop.

Changes

Cohort / File(s) Summary
Project Page Error UI
app/projects/new/page.tsx
Updated error handling to remove exception re-throw in catch block, added AlertCircle icon import, and refactored error display from FileUpload prop to a dedicated red alert panel below the component with onFileSelect wrapper to clear errors on file selection.
Upload API Client
lib/api/client.ts
Added 300-second timeout to uploadFileWithProgress and replaced generic error handling with CORS HEAD request to distinguish network unreachability from server errors, plus dedicated timeout event handler returning ApiError with status 0.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A rabbit's whisper on the breeze:
Five minutes now won't bring you to your knees,
When uploads fail or networks stall,
We catch the errors, we catch them all!
With alerts so red and timeouts clear,
No mystery remains, my dear. 🌟

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: improving import error UX with a server-reachability probe mechanism, which is the core improvement across both modified files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/import-error-handling
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/projects/new/page.tsx (1)

320-328: Announce the import failure banner to assistive tech.

This new panel is visually clear, but it will not be announced automatically when it appears. Adding role="alert" makes the failure much easier to notice for screen-reader users.

Suggested change
-                    <div className="mt-3 flex items-start gap-2 rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400">
+                    <div
+                      role="alert"
+                      className="mt-3 flex items-start gap-2 rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-700 dark:border-red-800 dark:bg-red-900/20 dark:text-red-400"
+                    >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/projects/new/page.tsx` around lines 320 - 328, The import failure banner
currently rendered when importError is truthy isn't announced to screen readers;
update the container div that renders the banner (the JSX block checking
importError) to include an accessibility announcement attribute such as
role="alert" (you may also add aria-live="assertive" if desired) so screen
readers automatically announce the error when the banner appears.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/api/client.ts`:
- Around line 198-199: The probe uses probe.ok (2xx-only) to set
serverReachable, which treats resolved non-2xx responses as unreachable; change
the logic in the probe block (where fetch(`${API_BASE}/`, ...) returns probe) to
treat any resolved Response as proof of reachability by setting serverReachable
= true when fetch resolves (and only mark unreachable on thrown network errors).
Update the code around the probe variable and serverReachable assignment to
reflect this (or alternatively point the probe at a dedicated health endpoint
that guarantees 2xx), ensuring the fetch rejection is the only condition that
sets serverReachable = false.

---

Nitpick comments:
In `@app/projects/new/page.tsx`:
- Around line 320-328: The import failure banner currently rendered when
importError is truthy isn't announced to screen readers; update the container
div that renders the banner (the JSX block checking importError) to include an
accessibility announcement attribute such as role="alert" (you may also add
aria-live="assertive" if desired) so screen readers automatically announce the
error when the banner appears.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b503b12e-0d1c-43e5-ac17-dca9f7012be2

📥 Commits

Reviewing files that changed from the base of the PR and between ec381d5 and dc36af1.

📒 Files selected for processing (2)
  • app/projects/new/page.tsx
  • lib/api/client.ts

Comment on lines +198 to +199
const probe = await fetch(`${API_BASE}/`, { method: "HEAD", mode: "cors" });
serverReachable = probe.ok;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Does the Fetch API resolve for HTTP 404/500 responses, and is Response.ok only true for 2xx statuses?

💡 Result:

Yes, the Fetch API resolves (does not reject) its Promise for HTTP 404 and 500 responses. These are considered valid HTTP responses, not network errors. The Promise only rejects on actual network failures (e.g., no connection, DNS failure). Yes, Response.ok is true only for 2xx status codes (200-299). It is false for 4xx, 5xx, and other non-successful statuses.

Citations:


Use any resolved fetch response to detect reachability, not just 2xx status codes.

When fetch() resolves successfully, the server is reachable—regardless of the HTTP status code. Checking probe.ok (true only for 2xx responses) will incorrectly classify a reachable server returning 401, 404, 405, or 500 as unreachable, which undermines the error handler's goal to distinguish between network failures and API errors.

Either accept any resolved response as proof of reachability:

-        const probe = await fetch(`${API_BASE}/`, { method: "HEAD", mode: "cors" });
-        serverReachable = probe.ok;
+        await fetch(`${API_BASE}/`, { method: "HEAD", mode: "cors" });
+        serverReachable = true;

Or probe a dedicated health endpoint that guarantees a 2xx response.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const probe = await fetch(`${API_BASE}/`, { method: "HEAD", mode: "cors" });
serverReachable = probe.ok;
await fetch(`${API_BASE}/`, { method: "HEAD", mode: "cors" });
serverReachable = true;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/api/client.ts` around lines 198 - 199, The probe uses probe.ok (2xx-only)
to set serverReachable, which treats resolved non-2xx responses as unreachable;
change the logic in the probe block (where fetch(`${API_BASE}/`, ...) returns
probe) to treat any resolved Response as proof of reachability by setting
serverReachable = true when fetch resolves (and only mark unreachable on thrown
network errors). Update the code around the probe variable and serverReachable
assignment to reflect this (or alternatively point the probe at a dedicated
health endpoint that guarantees 2xx), ensuring the fetch rejection is the only
condition that sets serverReachable = false.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant