Files
frontend-svelte/src/entities/Font/lib/errors/errors.ts
T
Ilia Mashkov 7f20f36d0a fix(api): mark schema-validation errors as non-retryable
The proxy returned `{fonts: null, total: 0}` for empty results, which
fetchProxyFonts surfaced as a generic Error. fontCatalogStore wrapped it
as FontNetworkError, and TanStack retried 3× with exponential backoff —
pinning the loading skeleton for ~7s before settling on an empty list.

Schema mismatches are deterministic; retrying only delays surfacing the
contract violation.

- shared/api/queryClient: introduce NonRetryableError marker class.
  The default retry handler short-circuits when it sees this so any
  store using the shared client gets fail-fast behavior for free.
- entities/Font/lib/errors: FontResponseError extends NonRetryableError.
- entities/Font/api/proxy/proxyFonts: throw FontResponseError (was a
  bare Error). Document that ProxyFontsResponse.fonts is always an array.
- entities/Font/.../fontCatalogStore.fetchPage: preserve a
  FontResponseError raised lower in the stack instead of re-wrapping
  it as FontNetworkError.
- features/FilterAndSortFonts/api/filters: throw NonRetryableError on
  invalid filters payloads and document the array-never-null contract.
2026-05-28 21:37:23 +03:00

33 lines
1.1 KiB
TypeScript

import { NonRetryableError } from '$shared/api/queryClient';
/**
* Thrown when the network request to the proxy API fails.
* Wraps the underlying fetch error (timeout, DNS failure, connection refused, etc.).
*/
export class FontNetworkError extends Error {
readonly name = 'FontNetworkError';
constructor(public readonly cause?: unknown) {
super('Failed to fetch fonts from proxy API');
}
}
/**
* Thrown when the proxy API returns a response with an unexpected shape.
* Extends NonRetryableError because schema mismatches are not transient —
* retrying will produce the same failure and only delay surfacing the bug.
*
* @property field - The name of the field that failed validation (e.g. `'response'`, `'response.fonts'`).
* @property received - The actual value received at that field, for debugging.
*/
export class FontResponseError extends NonRetryableError {
readonly name = 'FontResponseError';
constructor(
public readonly field: string,
public readonly received: unknown,
) {
super(`Invalid proxy API response: ${field}`);
}
}