Skip to content

fix: improve API error messages and auth failure UX#2051

Merged
AndreyHirsa merged 2 commits intomainfrom
fix/improve-api-error-messages
Mar 20, 2026
Merged

fix: improve API error messages and auth failure UX#2051
AndreyHirsa merged 2 commits intomainfrom
fix/improve-api-error-messages

Conversation

@AndreyHirsa
Copy link
Copy Markdown
Contributor

@AndreyHirsa AndreyHirsa commented Mar 20, 2026

Summary

Improve API error messages by parsing server response bodies and surfacing actionable auth failure messages instead of generic HTTP status text.

Changes

  • SDK: extractErrorMessage helper — parses JSON error responses from the API, extracting .message field or formatting NotFoundError, instead of relying on res.statusText
  • SDK: throwOnHttpError helper — deduplicates error-handling logic across localizeChunk and recognizeLocale
  • SDK: whoami removes try/catch — network errors (DNS, timeout) now propagate instead of being silently swallowed as null, which caused misleading "Invalid API key" messages when the server was unreachable
  • SDK: removed unused workflowId — was passed through _localizeRawlocalizeChunk but never included in the request body
  • CLI: checkAuth returns specific error — "Invalid API key" message when whoami returns null (401), real error message when whoami throws (network/server errors)

Testing

Business logic tests added:

  • All existing SDK tests pass
  • All existing CLI tests pass
  • Manual test: invalid API key shows "Invalid API key. Run lingo.dev login or check your LINGO_API_KEY."
  • Manual test: unreachable API URL shows real network error instead of "Invalid API key"

Visuals

N/A

Checklist

  • Changeset added
  • Tests cover business logic (not just happy path)
  • No breaking changes (or documented below)

Summary by CodeRabbit

  • Bug Fixes
    • Improved API error messages with details extracted from server responses instead of generic HTTP status text
    • Enhanced CLI authentication error reporting to display specific messages (e.g., "Invalid API key") rather than generic failure messages
    • Network failures now properly surface as errors

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c0077fe5-7b2b-4d60-a8aa-b8a1179eccba

📥 Commits

Reviewing files that changed from the base of the PR and between 7bb5c29 and 6092677.

📒 Files selected for processing (1)
  • .changeset/gentle-gifts-tell.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • .changeset/gentle-gifts-tell.md

📝 Walkthrough

Walkthrough

This patch release improves SDK error messaging by extracting details from JSON responses and consolidates HTTP error handling into shared utilities. The whoami endpoint's control flow is simplified by removing try/catch wrapping, and the unused workflowId parameter is removed. CLI authentication errors now report specific messages instead of generic failures.

Changes

Cohort / File(s) Summary
Changeset
.changeset/gentle-gifts-tell.md
Added changeset documenting patch release for lingo.dev and @lingo.dev/_sdk with improved error messaging, simplified control flow, and removed unused parameters.
SDK Error Handling
packages/sdk/src/index.ts
Introduced extractErrorMessage() and throwOnHttpError() helper methods to centralize HTTP error handling and parsing. Refactored localizeChunk, recognizeLocale, and whoami to use consolidated error handling; removed workflowId generation and parameter passing.
CLI Authentication
packages/cli/src/cli/localizer/lingodotdev.ts
Updated checkAuth to explicitly handle falsy whoami() responses with specific error message ("Invalid API key...") instead of deriving authentication state from response truthiness.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • vrcprl
  • cherkanovart

Poem

🐰 Hop along, dear errors now extracted clean,
No workflowIds cluttering the scene!
Whoami's freed from catch-block's embrace,
Smart messages guide users to the right place.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main objective: improving API error messages and authentication failure UX, which aligns with all key changes in the changeset.
Description check ✅ Passed The description covers all required template sections with appropriate detail: summary, changes, testing (with both automated and manual tests), and a nearly-complete checklist. All critical sections are substantively filled out.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/improve-api-error-messages
📝 Coding Plan
  • Generate coding plan for human review comments

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

Tip

You can enable review details to help with troubleshooting, context usage and more.

Enable the reviews.review_details setting to include review details such as the model used, the time taken for each step and more in the review comments.

Copy link
Copy Markdown
Contributor

@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)
packages/sdk/src/index.ts (1)

184-184: Consider adding context for localization errors.

Unlike recognizeLocale which passes "Error recognizing locale" as context, localizeChunk calls throwOnHttpError without context. For 401/403/404 errors, the user will see only the extracted message without operation context. This is a minor inconsistency.

Optional: Add context
-    await LingoDotDevEngine.throwOnHttpError(res);
+    await LingoDotDevEngine.throwOnHttpError(res, "Error localizing content");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sdk/src/index.ts` at line 184, The call in localizeChunk to
LingoDotDevEngine.throwOnHttpError(res) lacks operation context so HTTP errors
show only the extracted message; update the call in localizeChunk to pass a
descriptive context string (e.g., "Error localizing chunk" or similar) like
recognizeLocale does, so replace the bare call to
LingoDotDevEngine.throwOnHttpError(res) with a call that supplies the context
argument to throwOnHttpError to provide clearer error messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/sdk/src/index.ts`:
- Around line 53-54: The NotFoundError branch uses parsed.entityType and
parsed.id directly which can be undefined; update the NotFoundError handling
(the branch checking parsed?._tag === "NotFoundError") to use safe fallbacks
(e.g., default entityType to "entity" or "unknown entity" and id to "unknown id"
or empty string) when constructing the message so it never produces "undefined
not found: undefined".

---

Nitpick comments:
In `@packages/sdk/src/index.ts`:
- Line 184: The call in localizeChunk to LingoDotDevEngine.throwOnHttpError(res)
lacks operation context so HTTP errors show only the extracted message; update
the call in localizeChunk to pass a descriptive context string (e.g., "Error
localizing chunk" or similar) like recognizeLocale does, so replace the bare
call to LingoDotDevEngine.throwOnHttpError(res) with a call that supplies the
context argument to throwOnHttpError to provide clearer error messages.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a2ffd22b-b91f-4606-a5fd-6f430bd22235

📥 Commits

Reviewing files that changed from the base of the PR and between 48f8b3b and 7bb5c29.

📒 Files selected for processing (4)
  • .changeset/gentle-gifts-tell.md
  • packages/cli/src/cli/cmd/run/index.ts
  • packages/cli/src/cli/localizer/lingodotdev.ts
  • packages/sdk/src/index.ts

Comment thread packages/sdk/src/index.ts
Comment on lines +53 to +54
if (parsed?._tag === "NotFoundError") {
return `${parsed.entityType} not found: ${parsed.id}`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add defensive checks for NotFoundError properties.

If the server sends { "_tag": "NotFoundError" } without entityType or id, this will produce the message "undefined not found: undefined". Consider adding fallback values.

Proposed fix
       if (parsed?._tag === "NotFoundError") {
-        return `${parsed.entityType} not found: ${parsed.id}`;
+        return `${parsed.entityType ?? "Entity"} not found: ${parsed.id ?? "unknown"}`;
       }
📝 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
if (parsed?._tag === "NotFoundError") {
return `${parsed.entityType} not found: ${parsed.id}`;
if (parsed?._tag === "NotFoundError") {
return `${parsed.entityType ?? "Entity"} not found: ${parsed.id ?? "unknown"}`;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/sdk/src/index.ts` around lines 53 - 54, The NotFoundError branch
uses parsed.entityType and parsed.id directly which can be undefined; update the
NotFoundError handling (the branch checking parsed?._tag === "NotFoundError") to
use safe fallbacks (e.g., default entityType to "entity" or "unknown entity" and
id to "unknown id" or empty string) when constructing the message so it never
produces "undefined not found: undefined".

@AndreyHirsa AndreyHirsa merged commit 9991515 into main Mar 20, 2026
13 checks passed
@AndreyHirsa AndreyHirsa deleted the fix/improve-api-error-messages branch March 20, 2026 13:09
vrcprl pushed a commit that referenced this pull request Apr 17, 2026
* fix: improve API error messages and auth failure UX
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.

2 participants