Skip to content

Fix/standardize provider errors - #811

Closed
y-naaz wants to merge 1 commit into
juspay:releasefrom
y-naaz:fix/standardize-provider-errors
Closed

y-naaz wants to merge 1 commit into
juspay:releasefrom
y-naaz:fix/standardize-provider-errors

Conversation

@y-naaz

@y-naaz y-naaz commented Feb 8, 2026 •

Copy link
Copy Markdown

Pull Request

Description

What does this PR do?

A clear and concise description of the changes in this pull request.

Related Issues

Does this PR close any issues?

Fixes #(issue number)
Closes #(issue number)
Relates to #(issue number)

Type of Change

Please select the type of change:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)
  • Performance improvement
  • Test coverage improvement
  • Build/CI configuration
  • Other (please describe):

Motivation and Context

Why is this change needed? What problem does it solve?

Provide context for reviewers:

  • Background information
  • Use case or scenario
  • Links to relevant discussions or documentation
  • Screenshots/GIFs (if UI-related)

Changes Made

What specific changes were made?

Provide a bullet-point list of the key changes:

  • Added X functionality to Y component
  • Modified Z behavior to handle edge case A
  • Updated documentation in file B
  • Refactored C for better performance

Breaking Changes

Does this PR introduce breaking changes?

  • No breaking changes
  • Yes, breaking changes (describe below)

If yes, describe:

  • What breaks?
  • Migration path for users
  • Deprecation warnings added?

Testing

How has this been tested?

Please describe the tests you ran and their results:

  • Unit tests added/updated
  • Integration tests added/updated
  • E2E tests pass
  • Manual testing completed
  • Tested with multiple providers: [list providers]
  • Tested on multiple platforms: [list platforms]

Test Coverage

  • All new code is covered by tests
  • Existing tests pass
  • Coverage percentage maintained or improved

Manual Testing Steps

Provide steps for manual testing:

  1. Set up environment with [...]
  2. Run command [...]
  3. Verify that [...]
  4. Check that [...]

Code Quality

Have you followed code quality standards?

  • Code follows the project's style guidelines (ESLint passes)
  • Code is properly formatted (Prettier applied)
  • Self-review of code completed
  • No console.log statements (using logger instead)
  • No hardcoded API keys or secrets
  • TypeScript strict mode compliance
  • Proper error handling implemented
  • TODO/FIXME comments reference issues

Documentation

Have you updated documentation?

  • JSDoc comments added/updated for public APIs
  • README.md updated (if needed)
  • Documentation in /docs updated (if needed)
  • Code examples added/updated (if needed)
  • CHANGELOG.md updated (if applicable)
  • Migration guide provided (if breaking changes)

Commit Message Format

Does your commit follow semantic commit conventions?

  • Commit message follows format: type(scope): description
  • Valid type used: feat, fix, docs, style, refactor, test, chore, build, ci, perf, revert
  • Scope specified (e.g., providers, cli, docs, middleware)

Example: feat(providers): add support for LiteLLM proxy

Dependencies

Does this PR add, update, or remove dependencies?

  • No dependency changes
  • Dependencies added (list below)
  • Dependencies updated (list below)
  • Dependencies removed (list below)

If yes, list dependencies and justification:

package-name@version - Reason for adding/updating

Performance Impact

Does this change affect performance?

  • No performance impact
  • Performance improved (provide metrics)
  • Performance degraded (justify why acceptable)

If applicable, provide benchmark results:

Before: X ms
After: Y ms
Improvement: Z%

Security Considerations

Are there any security implications?

  • No security implications
  • Security review needed
  • Security vulnerability fixed

If applicable, describe:

  • Security measures implemented
  • Potential risks mitigated
  • Compliance considerations (HIPAA, SOC2, GDPR)

Deployment Notes

Special deployment instructions?

  • No special deployment steps
  • Requires environment variable changes (list below)
  • Requires database migration
  • Requires Redis schema update
  • Other (describe below)

Screenshots / Videos

If applicable, add screenshots or videos to demonstrate changes:

[Add screenshots or videos here]

Reviewer Checklist

For reviewers:

  • Code follows project style and conventions
  • Changes are well-documented
  • Tests provide adequate coverage
  • No obvious performance issues
  • No security vulnerabilities introduced
  • Breaking changes are properly documented
  • Documentation is clear and accurate

Additional Notes

Any additional information for reviewers:

[Add any extra context, concerns, or questions here]


Pre-submission Checklist

Before submitting, ensure you have:

  • Read and followed the Contributing Guidelines
  • Verified all automated pre-commit checks pass
  • Tested changes locally with pnpm test
  • Built the project successfully with pnpm build
  • Run pnpm run validate:all and all checks pass
  • Reviewed your own code for obvious issues
  • Ensured commit messages follow semantic format
  • Updated relevant documentation
  • Added tests for new functionality
  • Checked that CI/CD pipeline passes (after creating PR)

Thank you for contributing to NeuroLink!

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced error reporting across all AI providers delivers specific, actionable error messages for authentication, rate limits, and connectivity issues
    • CSV file processing now includes detailed column metadata analysis, data quality warnings, and overall quality scoring
  • Bug Fixes

    • Improved error handling prevents generic error messages and provides clearer diagnostics

Copilot AI review requested due to automatic review settings February 8, 2026 11:15
@coderabbitai

coderabbitai Bot commented Feb 8, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f5fad191-bb8d-4c83-864e-c3afc2167570

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR introduces centralized error detection and typed error handling across AI provider integrations, replacing generic error returns with specific error classes. Additionally, CSV processing is enhanced with column metadata analysis, data quality warnings, and quality scoring capabilities.

Changes

Cohort / File(s) Summary
Error Detection Framework
src/lib/types/errors.ts
Introduces detectProviderError() function with pattern-based error classification, ErrorDetectionPatterns interface, DEFAULT_ERROR_PATTERNS constants, and helper utilities (extractErrorMessage(), extractStatusCode(), isTimeoutError()) for centralized error detection across providers.
Provider Error Handling Refactoring
src/lib/providers/amazonBedrock.ts, src/lib/providers/anthropicBaseProvider.ts, src/lib/providers/azureOpenai.ts, src/lib/providers/googleVertex.ts, src/lib/providers/huggingFace.ts, src/lib/providers/litellm.ts, src/lib/providers/mistral.ts, src/lib/providers/ollama.ts, src/lib/providers/openRouter.ts
Refactors handleProviderError() across all providers to use detectProviderError() for automatic error classification, replacing generic Error returns with typed errors (AuthenticationError, RateLimitError, NetworkError, InvalidModelError, ProviderError). Amazon Bedrock adds checkBedrockHealth() method for connectivity validation.
CSV Processing Enhancements
src/lib/types/fileTypes.ts
Extends FileProcessingResult with new fields: columnMetadata, dataQualityWarnings, dataQualityScore, hasHeaders, detectedDelimiter. Introduces new types: CSVColumnDataType, CSVColumnMetadata, CSVDataQualityWarning for rich column-level analysis and quality reporting.
CSV Processing Implementation
src/lib/utils/csvProcessor.ts
Adds comprehensive column analysis: type detection (string, number, date, email, etc.) with confidence scores, null/unique counts, sample values, numeric/date statistics, and column name validation. Integrates data quality warning generation and scoring into both raw and structured format processing paths.
CSV Processor Tests
test/unit/utils/csvProcessor.test.ts
Adds 361 lines of test coverage for column metadata analysis, data quality warnings, data quality scoring, and header detection across various CSV formats and edge cases.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

released

Suggested reviewers

  • murdore
  • coder-dodo

Poem

🐰 With errors caught and typed with care,
And CSV columns analyzed fair,
The data flows, both clean and bright,
Each provider now gets errors right!
A framework born to guide the way,
Making code more stable every day! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix/standardize provider errors' directly aligns with the main objective: standardizing error handling across multiple provider implementations by introducing typed error classes and a centralized error detection utility.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/lib/providers/litellm.ts (1)

101-173: ⚠️ Potential issue | 🟠 Major

Change handleProviderError return type from Error to never across all providers.

All 14 providers have handleProviderError(error: unknown): Error, but every code path throws. The return type is misleading and violates TypeScript's contract. Since the method always throws (never returns), the return type should be never, and call sites should remove the outer throw:

  • Change: public handleProviderError(error: unknown): Error → public handleProviderError(error: unknown): never
  • At call sites: throw this.handleProviderError(error) → this.handleProviderError(error)

This applies to all 14 providers: litellm.ts, openAI.ts, mistral.ts, openRouter.ts, huggingFace.ts, googleAiStudio.ts, ollama.ts, azureOpenai.ts, anthropic.ts, amazonSagemaker.ts, googleVertex.ts, amazonBedrock.ts, openaiCompatible.ts, anthropicBaseProvider.ts.

src/lib/providers/mistral.ts (1)

173-221: ⚠️ Potential issue | 🟠 Major

Same handleProviderError return-type / throw mismatch as in googleVertex.ts.

This method's return type is Error but every branch throws. The same fix applies: change return type to never (pending base class update).

Beyond that, the error classification logic is clean and correctly maps Mistral-specific error patterns to typed errors. The detectProviderError pre-check followed by provider-specific fallbacks is a sound layered approach.

Proposed fix
-  public handleProviderError(error: unknown): Error {
+  public handleProviderError(error: unknown): never {
🤖 Fix all issues with AI agents
In `@src/lib/providers/anthropicBaseProvider.ts`:
- Around line 56-97: The handleProviderError function should have a never return
type and avoid redundant status-code branches already handled by
detectProviderError: change the signature from "protected
handleProviderError(error: unknown): Error" to "protected
handleProviderError(error: unknown): never", keep the detectProviderError(error,
this.providerName) and TimeoutError handling, and then either remove the
explicit status checks for 401 and 429 (the AuthenticationError/RateLimitError
branches) or add a clear comment that they are intentional fallbacks; ensure
thrown errors remain NetworkError, AuthenticationError, RateLimitError,
ProviderError as currently used and reference these symbols when modifying the
code.

In `@src/lib/providers/azureOpenai.ts`:
- Around line 88-130: In handleProviderError, detectProviderError is currently
called first and throws before Azure-specific checks can provide tailored
guidance; move the detectProviderError call to the end of handleProviderError
(after the AuthenticationError, RateLimitError, NetworkError, and ProviderError
checks) so provider-specific message logic in handleProviderError runs first and
only falls back to detectProviderError/detectedError if no manual pattern
matched; reference handleProviderError, detectProviderError, and
DEFAULT_ERROR_PATTERNS when making the change and preserve throwing the detected
error when it is returned at the end.

In `@src/lib/types/errors.ts`:
- Around line 84-122: The DEFAULT_ERROR_PATTERNS contains the numeric substring
patterns "401" and "429" which are too broad and cause false positives because
matchesPatterns does a substring check; remove "401" from the authentication
array and "429" from the rateLimit array in DEFAULT_ERROR_PATTERNS and rely on
extractStatusCode/statusCodes handling for numeric HTTP status detection (see
matchesPatterns and extractStatusCode references to guide locating the logic).
- Line 148: The patterns assignment currently shallow-merges
DEFAULT_ERROR_PATTERNS and customPatterns, causing whole arrays to be replaced;
update the merge so for each error category key (use DEFAULT_ERROR_PATTERNS and
customPatterns) you concatenate/merge the arrays (e.g.,
DEFAULT_ERROR_PATTERNS[key].concat(customPatterns[key]) with sensible defaults
when a key is missing) and optionally deduplicate entries, then assign the
result to patterns so providers can extend rather than overwrite defaults.

In `@src/lib/utils/csvProcessor.ts`:
- Around line 109-117: BOOLEAN_VALUES currently runs before numeric detection so
"1"/"0" get classified as boolean; change the check order to test numeric types
first by moving the INTEGER_REGEX (and FLOAT_REGEX if present) checks above the
BOOLEAN_VALUES check (i.e., run INTEGER_REGEX.test(trimmed) and any float test
before consulting BOOLEAN_VALUES), or alternatively remove "1" and "0" from
BOOLEAN_VALUES; update the logic in the type-detection function that uses
BOOLEAN_VALUES and INTEGER_REGEX accordingly so numeric strings are classified
as integer/float before being treated as boolean.

In `@test/unit/utils/csvProcessor.test.ts`:
- Around line 549-601: The test indicates 0 and 1 are being misclassified as
boolean because the type detection checks boolean before integer; update the
detection logic in detectValueType (or wherever value classification occurs in
CSVProcessor) to check integer/number types before boolean so numeric values 0
and 1 are classified as integers/floats, not booleans, then adjust or re-run the
"should consolidate integers and floats as number type" test to include natural
0/1 values if desired to confirm the fix.
🧹 Nitpick comments (8)
src/lib/utils/csvProcessor.ts (4)

277-283: Math.min(...numericValues) / Math.max(...) can throw RangeError on large arrays.

With maxRows up to 10,000, the spread operator passes all elements as function arguments, which can exceed the JS engine's call stack limit (typically ~65K–125K args, but behavior varies). For a fully numeric column with 10,000 rows this is likely fine, but it's a latent risk if limits are raised.

A simple loop or reduce avoids this entirely:

Proposed fix
   if (numericValues.length > 0) {
-    minValue = Math.min(...numericValues);
-    maxValue = Math.max(...numericValues);
+    minValue = numericValues.reduce((a, b) => Math.min(a, b), numericValues[0]);
+    maxValue = numericValues.reduce((a, b) => Math.max(a, b), numericValues[0]);
     avgValue =
       Math.round(
         (numericValues.reduce((a, b) => a + b, 0) / numericValues.length) * 100,
       ) / 100;
   }

686-692: Raw format re-parses the CSV solely for metadata analysis — potential performance hit.

The raw path already has the CSV string available but now re-parses it through the streaming CSV parser (up to 500 rows) just to populate column metadata. For large files this roughly doubles processing time in the raw path.

Consider whether this trade-off is intentional. If metadata is not always needed, a lazy or opt-in approach would be lighter. Otherwise this is acceptable if metadata is always consumed downstream.


389-429: Quality score can be double-penalized for the same issue.

calculateDataQualityScore deducts points per warning (e.g., high_null_rate warning → −3 or −8) and also deducts for overall null rate (Line 419) and low type confidence (Lines 424-426). A column with high nulls thus gets penalized via both the warning deduction and the null-rate deduction. This may be intentional for weighting, but it makes the score harder to reason about and could yield unexpectedly low scores for moderately problematic data.


716-720: Raw format header detection splits on comma only — ignores other delimiters.

(limitedLines[0] || "").split(",") at Line 717 assumes comma delimiter. If the CSV uses tabs or semicolons, header detection will receive a single-element array and likely return incorrect results. The detectedDelimiter is also hardcoded to "," at Line 720. This is consistent but worth noting if multi-delimiter support is planned.

test/unit/utils/csvProcessor.test.ts (1)

804-845: Data quality score tests are adequate but could benefit from boundary testing.

Consider adding a test that verifies the score is clamped to [0, 100] — e.g., extremely problematic data shouldn't yield a negative score. The implementation does Math.max(0, Math.min(100, score)), but there's no test asserting the lower bound explicitly for worst-case input.

src/lib/types/errors.ts (1)

143-178: AuthorizationError (403) is not handled by detectProviderError.

The file defines AuthorizationError (Line 36), but detectProviderError has no pattern category or status code check for it. HTTP 403 / "Forbidden" / "AccessDenied" errors will fall through and return null. The Bedrock provider manually handles AccessDeniedException after detectProviderError returns null, but other providers may not. Consider adding an authorization category to ErrorDetectionPatterns with status code [403] and patterns like "Forbidden", "AccessDenied", "access_denied".

src/lib/providers/litellm.ts (1)

102-106: Redundant timeout detection after detectProviderError.

detectProviderError already detects TimeoutError and AbortError (via isTimeoutError) and returns a generic NetworkError("Request timed out"). The manual TimeoutError / "Timeout" checks on lines 108–126 will never execute for timeout errors because detectProviderError throws first.

If the intent is to preserve the more descriptive LiteLLM-specific message ("LiteLLM request timed out: ..."), pass custom timeout patterns that won't match in detectProviderError and handle timeouts manually. Otherwise, the lines 108–126 are dead code.

This same redundancy exists in other providers (HuggingFace, OpenRouter, Ollama). Not blocking, but worth being aware of.

Also applies to: 108-126

src/lib/providers/googleVertex.ts (1)

2331-2335: Potential double-throw: detectProviderError may already classify timeouts that the next block also checks.

detectProviderError calls isTimeoutError(error) internally and returns a NetworkError for timeouts. The explicit TimeoutError check at lines 2338-2346 is therefore a defensive fallback for cases where detectProviderError's heuristic doesn't match (e.g., a custom TimeoutError class with .name === "TimeoutError"). This is fine as-is but worth noting that the two checks overlap significantly. No action needed unless you want to simplify.

Comment thread src/lib/providers/anthropicBaseProvider.ts Outdated
Comment thread src/lib/providers/azureOpenai.ts Outdated
Comment on lines 88 to 130
public handleProviderError(error: unknown): Error {
const errorObj = error as UnknownRecord;
if (
errorObj?.message &&
typeof errorObj.message === "string" &&
errorObj.message.includes("401")
) {
return new Error("Invalid Azure OpenAI API key or endpoint.");
// Try automatic error detection first
const detectedError = detectProviderError(error, this.providerName);
if (detectedError) {
throw detectedError;
}

const errorObj = error as UnknownRecord;
const message =
errorObj?.message && typeof errorObj.message === "string"
? errorObj.message
: "Unknown error";
return new Error(`Azure OpenAI error: ${message}`);

if (message.includes("401") || message.includes("Unauthorized")) {
throw new AuthenticationError(
"Invalid Azure OpenAI API key or endpoint. Please check your AZURE_OPENAI_API_KEY and AZURE_OPENAI_ENDPOINT environment variables.",
this.providerName,
);
}

if (message.includes("429") || message.includes("rate limit")) {
throw new RateLimitError(
"Azure OpenAI rate limit exceeded. Please try again later.",
this.providerName,
);
}

if (
message.includes("ECONNREFUSED") ||
message.includes("ENOTFOUND") ||
message.includes("fetch failed")
) {
throw new NetworkError(
`Azure OpenAI connection error: ${message}`,
this.providerName,
);
}

throw new ProviderError(
`Azure OpenAI error: ${message}`,
this.providerName,
);
}

@coderabbitai coderabbitai Bot Feb 8, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

detectProviderError shadows all Azure-specific error messages.

Every manual check below detectProviderError (lines 101–124) matches patterns that are already in DEFAULT_ERROR_PATTERNS — e.g., "401", "Unauthorized", "429", "rate limit", "ECONNREFUSED", "ENOTFOUND". Since detectProviderError throws first with the raw error message, the carefully crafted Azure-specific guidance messages (like "check your AZURE_OPENAI_API_KEY and AZURE_OPENAI_ENDPOINT") will never reach the user.

This is a correctness concern affecting user experience — the whole point of provider-specific messages is lost. The same issue applies to other providers but is most impactful here since Azure requires multiple environment variables.

Options:

  1. Move detectProviderError to the end as a fallback, after provider-specific checks.
  2. Don't call detectProviderError and rely solely on manual checks (since they already cover the same cases with better messages).
  3. Have detectProviderError return the error instead of throwing, and only throw it if no manual check matched.
Option 1: Move detectProviderError to end as fallback
   public handleProviderError(error: unknown): Error {
-    // Try automatic error detection first
-    const detectedError = detectProviderError(error, this.providerName);
-    if (detectedError) {
-      throw detectedError;
-    }
-
     const errorObj = error as UnknownRecord;
     const message = /* ... */;

     if (message.includes("401") || message.includes("Unauthorized")) {
       throw new AuthenticationError(/* Azure-specific message */, this.providerName);
     }
     // ... other manual checks ...

+    // Fallback: try automatic error detection
+    const detectedError = detectProviderError(error, this.providerName);
+    if (detectedError) {
+      throw detectedError;
+    }
+
     throw new ProviderError(`Azure OpenAI error: ${message}`, this.providerName);
   }
🤖 Prompt for AI Agents
In `@src/lib/providers/azureOpenai.ts` around lines 88 - 130, In
handleProviderError, detectProviderError is currently called first and throws
before Azure-specific checks can provide tailored guidance; move the
detectProviderError call to the end of handleProviderError (after the
AuthenticationError, RateLimitError, NetworkError, and ProviderError checks) so
provider-specific message logic in handleProviderError runs first and only falls
back to detectProviderError/detectedError if no manual pattern matched;
reference handleProviderError, detectProviderError, and DEFAULT_ERROR_PATTERNS
when making the change and preserve throwing the detected error when it is
returned at the end.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the current state of handleProviderError in azureOpenai.ts
rg -n "handleProviderError|detectProviderError|AuthenticationError|RateLimitError|NetworkError|ProviderError" src/lib/providers/azureOpenai.ts -A2 -B2

Length of output: 338


🏁 Script executed:

#!/bin/bash
# Get the full content of formatProviderError / handleProviderError methods
sed -n '84,140p' src/lib/providers/azureOpenai.ts

Length of output: 1933


@y-naaz, I checked the current state of src/lib/providers/azureOpenai.ts on the branch and it looks like the changes have been fully reverted to the original pre-PR implementation — the file now contains formatProviderError with plain Error returns and none of the typed errors (AuthenticationError, RateLimitError, etc.) or detectProviderError are present.

Could you clarify the intended resolution? There are a few possibilities:

  1. Intentionally reverted — The changes to azureOpenai.ts were dropped from this PR entirely, in which case this comment can be dismissed.
  2. Fix applied incorrectly — The suggested fix (moving detectProviderError to the end as a fallback) was supposed to be applied to the handleProviderError method introduced in the diff, but wasn't pushed correctly.

If the intent is to apply the fix, the corrected version should look like:

public handleProviderError(error: unknown): Error {
  const errorObj = error as UnknownRecord;
  const message =
    errorObj?.message && typeof errorObj.message === "string"
      ? errorObj.message
      : "Unknown error";

  if (message.includes("401") || message.includes("Unauthorized")) {
    throw new AuthenticationError(
      "Invalid Azure OpenAI API key or endpoint. Please check your AZURE_OPENAI_API_KEY and AZURE_OPENAI_ENDPOINT environment variables.",
      this.providerName,
    );
  }

  if (message.includes("429") || message.includes("rate limit")) {
    throw new RateLimitError(
      "Azure OpenAI rate limit exceeded. Please try again later.",
      this.providerName,
    );
  }

  if (
    message.includes("ECONNREFUSED") ||
    message.includes("ENOTFOUND") ||
    message.includes("fetch failed")
  ) {
    throw new NetworkError(
      `Azure OpenAI connection error: ${message}`,
      this.providerName,
    );
  }

  // Fallback: try automatic error detection
  const detectedError = detectProviderError(error, this.providerName);
  if (detectedError) {
    throw detectedError;
  }

  throw new ProviderError(`Azure OpenAI error: ${message}`, this.providerName);
}

🧠 Learnings used
Learnt from: murdore
Repo: juspay/neurolink PR: 0
File: :0-0
Timestamp: 2026-02-22T14:18:13.480Z
Learning: In the neurolink providers, formatProviderError must return typed errors (not throw). For Google Vertex specifically, timeouts and common network errors (ECONNRESET, ENOTFOUND, ECONNREFUSED) are mapped to NetworkError for consistency across providers.

Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 173
File: src/lib/index.ts:16-16
Timestamp: 2025-09-17T17:55:15.261Z
Learning: In src/lib/types/providers.ts, ProviderConfig was renamed to AIModelProviderConfig to deduplicate type names, as there was an existing ProviderConfig type that better suited the "ProviderConfig" name. This was an intentional breaking change for better type organization.

Learnt from: YasmeenOgo
Repo: juspay/neurolink PR: 145
File: src/lib/core/types.ts:0-0
Timestamp: 2025-09-02T13:50:42.770Z
Learning: The APIVersions enum in src/lib/core/types.ts now contains comprehensive API version constants for all major AI providers: Azure OpenAI (latest, stable, legacy), OpenAI (current, beta), Google AI (current, beta), and Anthropic (current). This centralization helps avoid API version drift across the codebase.

Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 173
File: src/lib/types/index.ts:58-62
Timestamp: 2025-09-17T18:14:34.960Z
Learning: RajuSudhar explained that in the Neurolink codebase, there are multiple ProviderConfig types causing inconsistency. One existing ProviderConfig type better suited the "ProviderConfig" name, so they renamed the less-suitable one to AIModelProviderConfig to free up the name. Adding backward compatibility aliases would worsen naming inconsistency rather than help. The remaining duplicates will be systematically deduplicated in the 07-Types-Module.md TODO as part of their phased refactor approach.

Learnt from: RajuSudhar
Repo: juspay/neurolink PR: 0
File: :0-0
Timestamp: 2025-11-04T22:14:18.719Z
Learning: In the juspay/neurolink repository, do not flag existing type or interface definitions located outside src/lib/types/ - these are part of a phased migration plan and will be addressed in upcoming PRs. Only enforce type centralization rules on new code going forward.

Learnt from: sudharsan-juspay
Repo: juspay/neurolink PR: 160
File: src/lib/providers/index.ts:43-44
Timestamp: 2025-09-10T08:22:11.910Z
Learning: In the Neurolink project, type deduplication across modules (like ProviderName definitions) should be handled as separate tasks rather than mixed with other refactoring efforts, as there are multiple such occurrences throughout the codebase that need systematic cleanup.

Comment thread src/lib/types/errors.ts Outdated
Comment thread src/lib/types/errors.ts Outdated
Comment thread src/lib/utils/csvProcessor.ts Outdated
Comment thread test/unit/utils/csvProcessor.test.ts

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR aims to standardize provider error handling by introducing a shared error-detection utility and updating multiple providers to emit consistent typed errors. In addition, it introduces enhanced CSV analysis (column type detection, data quality warnings, quality scoring, and header detection) along with extensive new unit tests for the CSV processor.

Changes:

  • Add detectProviderError() and default message-pattern matching to classify provider errors into typed ProviderError subclasses.
  • Update multiple providers to use the standardized typed errors for auth/rate-limit/network/model failures.
  • Add CSV column metadata analysis (types/statistics), data quality warnings/scoring, and header detection + new unit tests covering the new metadata.

Reviewed changes

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

Show a summary per file
File Description
src/lib/types/errors.ts Adds shared error pattern detection (detectProviderError) and supporting helpers/constants.
src/lib/providers/openRouter.ts Switches OpenRouter error handling to standardized typed errors and auto-detection.
src/lib/providers/ollama.ts Updates Ollama error mapping to standardized typed errors and auto-detection.
src/lib/providers/mistral.ts Updates Mistral error mapping to standardized typed errors and auto-detection.
src/lib/providers/litellm.ts Updates LiteLLM error mapping to standardized typed errors and auto-detection.
src/lib/providers/huggingFace.ts Updates HuggingFace error mapping to standardized typed errors and auto-detection.
src/lib/providers/googleVertex.ts Updates Vertex error mapping to standardized typed errors and auto-detection.
src/lib/providers/azureOpenai.ts Updates Azure OpenAI error mapping to standardized typed errors and auto-detection.
src/lib/providers/anthropicBaseProvider.ts Updates Anthropic base provider error mapping to standardized typed errors and auto-detection.
src/lib/providers/amazonBedrock.ts Updates Bedrock error mapping to standardized typed errors and auto-detection.
src/lib/utils/csvProcessor.ts Adds enhanced CSV metadata analysis (column typing, warnings, score, header detection).
src/lib/types/fileTypes.ts Extends CSV-related metadata types to expose column metadata, warnings, score, header/delimiter info.
test/unit/utils/csvProcessor.test.ts Adds comprehensive unit tests for the new CSV metadata and quality features.

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

Comment thread src/lib/providers/openRouter.ts Outdated
Comment on lines +130 to +134
public handleProviderError(error: unknown): Error {
// Try automatic error detection first
const detectedError = detectProviderError(error, this.providerName);
if (detectedError) {
throw detectedError;

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

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

handleProviderError() now throws (including the detectProviderError fast-path). Existing integration tests call this method directly and expect it to return an Error instance (e.g., const handledError = provider.handleProviderError(error)). To avoid breaking that contract, either revert to returning the typed errors (and let callers throw), or update the public API/tests + BaseProvider contract to make handleProviderError consistently throw across providers.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

Comment thread src/lib/types/errors.ts Outdated
Comment on lines +148 to +152
const patterns = { ...DEFAULT_ERROR_PATTERNS, ...customPatterns };

// Extract error message from various error shapes
const message = extractErrorMessage(error);
const statusCode = extractStatusCode(error);

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

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

customPatterns is merged via object spread. If a caller passes { authentication: undefined } (or similar), it will overwrite the default array with undefined, and subsequent matchesPatterns() calls will throw at runtime because they assume string[]. Consider per-field nullish merging (e.g. custom?.authentication ?? DEFAULT...) or sanitizing customPatterns before use.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

Comment thread src/lib/types/errors.ts Outdated
Comment on lines +75 to +79
rateLimit?: string[];
network?: string[];
invalidModel?: string[];
timeout?: string[];
}

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

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

ErrorDetectionPatterns exposes a timeout pattern list, but detectProviderError() never consults patterns.timeout (it only calls isTimeoutError). Either incorporate timeout patterns into detection logic or remove the unused field/defaults to avoid a misleading API surface.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

Comment thread src/lib/utils/csvProcessor.ts Outdated
Comment on lines +519 to +522
const uniqueHeaders = new Set(
headerValues.map((v) => v?.trim().toLowerCase()),
);
const hasUniqueHeaders = uniqueHeaders.size === headerValues.length;

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

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

detectHasHeaders() treats empty headers as allowed, but uniqueness is checked across all trimmed header values (including ''), and compared to headerValues.length. Multiple empty header cells will therefore force hasUniqueHeaders to false and can incorrectly return hasHeaders=false. Consider excluding empty/blank header names from the uniqueness check (or updating the comment/behavior to disallow empty headers).

Suggested change
const uniqueHeaders = new Set(
headerValues.map((v) => v?.trim().toLowerCase()),
);
const hasUniqueHeaders = uniqueHeaders.size === headerValues.length;
// Uniqueness is evaluated only among non-empty header names; empty headers are allowed.
const normalizedNonEmptyHeaders = headerValues
.map((v) => v?.trim().toLowerCase())
.filter((v) => v !== "");
const uniqueHeaders = new Set(normalizedNonEmptyHeaders);
const hasUniqueHeaders =
uniqueHeaders.size === normalizedNonEmptyHeaders.length;

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

Comment thread src/lib/utils/csvProcessor.ts Outdated
Comment on lines +716 to +720
hasHeaders: detectHasHeaders(
(limitedLines[0] || "").split(","),
undefined,
),
detectedDelimiter: ",",

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

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

In the raw-format path, hasHeaders is computed via (limitedLines[0] || "").split(",") and detectedDelimiter is hardcoded to ",". This bypasses proper CSV parsing (quotes/escaped commas) and ignores sep=... metadata lines (which are detected elsewhere). Since you already parse limitedCSV into sampleForAnalysis, consider deriving headers (and delimiter, if supported) from the parser result instead of manual splitting, or rename the field to reflect that it’s an assumed delimiter.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

Comment on lines +686 to +690
// Parse a sample for enhanced metadata analysis (raw format still benefits from column analysis)
const sampleForAnalysis = await this.parseCSVString(
limitedCSV,
Math.min(rowCount, 500),
);

Copilot AI Feb 8, 2026

Copy link

Choose a reason for hiding this comment

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

The PR title/description focuses on standardizing provider errors, but this change also adds substantial new CSV column/type analysis + data-quality scoring (and a large new test suite). Please either update the PR title/description to reflect the CSV feature, or split the CSV work into a separate PR to keep scope and risk contained.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done

@y-naaz
y-naaz force-pushed the fix/standardize-provider-errors branch 2 times, most recently from 1b748a6 to d1923a2 Compare February 8, 2026 11:49
@vercel

vercel Bot commented Mar 7, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Sachin Sharma's projects Team on Vercel.

A member of the Team first needs to authorize it.

All providers now use typed ProviderError subclasses (AuthenticationError,
RateLimitError, NetworkError, InvalidModelError, AuthorizationError) instead
of plain Error objects. This enables programmatic error handling and consistent
error classification across all 13 providers.

Changes:
- Added detectProviderError() utility in errors.ts for automatic error type detection
- Updated 9 providers to throw typed errors: AnthropicBase, LiteLLM, Bedrock,
  Azure, Vertex, Mistral, Ollama, OpenRouter, HuggingFace
- All handleProviderError() methods now use throw instead of return
- Provider-specific error patterns preserved with helpful error messages

Fixes bug where different providers returned inconsistent error formats.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@y-naaz
y-naaz force-pushed the fix/standardize-provider-errors branch from a0af671 to cf5f164 Compare March 7, 2026 10:17
@murdore
murdore force-pushed the release branch 2 times, most recently from 09ff4a5 to 405e3e5 Compare March 12, 2026 10:48
@murdore

murdore commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Closing as part of project audit (2026-03-29). The feature this PR targets was implemented via a different approach in a later release. See docs/project-audit-2026-03-29.md for details.

@murdore murdore closed this Mar 29, 2026
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.

3 participants