Production reliability
Predictable failure modes when @media-sdk/core runs against real provider APIs. This matrix links scenarios to expected errors and test coverage.
For handler patterns, see Errors and Error handling recipes.
Failure mode matrix
| Scenario | Expected behavior | MediaError / error type | Tested |
|---|---|---|---|
| HTTP 401 Unauthorized | Reject; no cache write | MediaError, status: 401 | Yes — FetchHttpClient.test.ts |
| HTTP 403 Forbidden | Reject; no cache write | MediaError, status: 403 | Yes — FetchHttpClient.test.ts, PixabayMediaClient.test.ts |
| HTTP 404 Not Found | Reject | MediaError, status: 404 | Yes — FetchHttpClient.test.ts |
| HTTP 429 Too Many Requests | Reject; no automatic retry | MediaError, status: 429 | Yes — FetchHttpClient.test.ts |
| HTTP 5xx (500, 503) | Reject | MediaError, status set | Yes — FetchHttpClient.test.ts |
| Malformed JSON on 2xx | Reject from response.json() | Native Error (not MediaError) | Yes — FetchHttpClient.test.ts |
Missing API key (ApiKeyProvider("")) | Throw at construction | Native Error | Yes — ApiKeyProvider.test.ts |
Network failure (fetch throws) | Propagate fetch error | Native Error (not MediaError) | Yes — FetchHttpClient.test.ts |
Request abort (AbortSignal) | AbortError / DOMException | Not MediaError | Yes — FetchHttpClient.test.ts, RequestManager.test.ts |
| Provider HTTP error via client | Propagate MediaError from HttpClient | MediaError + status | Yes — PexelsMediaClient.test.ts, PixabayMediaClient.test.ts |
| Provider network error via client | Propagate native Error | Not MediaError | Yes — PexelsMediaClient.test.ts |
| Failed request not cached | Retry allowed on same key | — | Yes — RequestManager.test.ts, PexelsMediaClient.test.ts |
| No built-in fetch timeout | fetch runs until browser/runtime completes or aborts | — | Documented (no SDK timeout) |
| Rate limit backoff | Not implemented — app responsibility | — | Documented |
| Unsupported operation | MediaError, code: UNSUPPORTED_CAPABILITY | Yes — provider tests | |
| Unsupported filter key | MediaError, code: UNSUPPORTED_FILTER | Yes — filter validation tests | |
| Invalid filter value | MediaError, code: INVALID_FILTER_VALUE | Yes — filter validation tests |
No built-in timeout
FetchHttpClient does not set AbortSignal.timeout or a custom deadline. Hung requests depend on the runtime and network stack.
Workaround: inject a custom HttpClient that wraps fetch with a timeout:
ts
import {
FetchHttpClient,
type HttpClient,
type HttpRequestOptions,
} from "@media-sdk/core";
function withTimeout(
inner: HttpClient,
timeoutMs: number,
): HttpClient {
return {
get<T>(url: string, options?: HttpRequestOptions): Promise<T> {
const controller = new AbortController();
const timeoutId = setTimeout(
() => controller.abort(),
timeoutMs,
);
const signal = options?.signal;
if (signal) {
if (signal.aborted) {
controller.abort();
} else {
signal.addEventListener("abort", () => controller.abort(), {
once: true,
});
}
}
return inner
.get(url, { ...options, signal: controller.signal })
.finally(() => clearTimeout(timeoutId));
},
};
}
const client = new PexelsMediaClient(auth, {
httpClient: withTimeout(
new FetchHttpClient(() => auth.getKey()),
10_000,
),
});Rate limits (429)
Providers enforce per-key limits. The SDK surfaces status === 429 as MediaError. Backoff and retry are app responsibilities — the SDK does not retry automatically.
Cache on failure
RequestManager does not cache rejected requests. A failed search can be retried without stale error entries. See Provider pages for TTL and deduplication.
Starter messaging
| Condition | Suggested UX |
|---|---|
| Missing env API key | Fail at createMediaClient / ApiKeyProvider with clear env var name |
| 401 / 403 | "Check API key for active provider" |
| 429 | "Rate limited — wait or reduce request rate" |
| Network / timeout | Generic retry message; check connectivity |
Related
- Errors — taxonomy
- Cancellation — abort behavior
- Performance baseline — latency baselines (mocked)