Тема
Ошибки
Библиотека нормализует Axios errors для UI и lifecycle callbacks, но не скрывает исходную ошибку при throw.
Нормализация
ts
import { normalizeAxiosError } from "@dubium/query-layer/axios"
try {
await users.refetch()
} catch (cause) {
const error = normalizeAxiosError(cause)
console.log({
code: error.code,
message: error.message,
status: error.status,
isAxiosError: error.isAxiosError,
})
}UI должен опираться на нормализованные поля, а не на внутреннюю структуру AxiosError.
Классификация
ts
import {
isForbiddenError,
isServerError,
isUnauthorizedError,
} from "@dubium/query-layer/axios"
if (isUnauthorizedError(error)) redirectToLogin()
else if (isForbiddenError(error)) showAccessDenied()
else if (isServerError(error)) showTemporaryFailure()Состояние ошибки в store
ts
if (users.isError) {
const status = users.error?.status
if (status === 404) showEmptyState()
else showRetryButton(() => users.refetch())
}При ошибке background refetch старые данные могут оставаться в data. Не заменяйте весь экран spinner/error, если hasData === true.
Политика повторов
ts
const store = createQueryStore({
queryKey: () => ["profile"],
queryFn: loadProfile,
retry: (failureCount, error) => {
const normalized = normalizeAxiosError(error)
if (normalized.status && normalized.status < 500) return false
return failureCount < 2
},
retryDelay: (failureCount) => Math.min(500 * 2 ** failureCount, 5_000),
})Не повторяйте небезопасную mutation автоматически без серверной идемпотентности.
Отмена
Cancellation — отдельный исход, а не пользовательская ошибка. Не показывайте toast при закрытии экрана.
ts
try {
await store.fetch()
} catch (error) {
if (error instanceof DOMException && error.name === "AbortError") return
throw error
}Axios также может вернуть CanceledError; внутренний lifecycle распознаёт оба варианта.
Timeout конкретного RequestStore-вызова
ts
const health = createRequestStore({
api: healthApi,
})
try {
// timeout — AxiosRequestConfig, а не поле RequestStore options.
await health.executeWithConfig([], { timeout: 3_000 })
} catch (error) {
if (health.error?.message.includes("timeout")) {
showMessage("Сервис отвечает слишком долго")
}
}Ошибки persistence
ts
const persistence = await persistQueryRuntime({
runtime,
persister,
onPersistError: (error) => {
logger.warn("cache persistence unavailable", { error })
},
})Cache persistence обычно деградирует мягко. Ошибка сохранения offline-команды, наоборот, может требовать блокировки пользовательского действия.
Ошибки orchestration
ts
import {
WorkflowExecutionError,
} from "@dubium/query-layer/orchestration"
try {
await workflow.execute()
} catch (error) {
if (error instanceof WorkflowExecutionError) {
console.log(error.failedNodeId, error.cause, error.compensationErrors)
}
}Сохраняйте в telemetry безопасные идентификаторы, но не request body, токены или persisted snapshots.