chore(logging): remove redundant errorCode fields from server logs and error contracts

Eliminate the errorCode property from server logger calls, error contract types, and API error bodies throughout the codebase. This reduces duplication and streamlines error reporting, relying on structured event names and error classes for identification. All affected API routes, server logic, and logging utilities have been updated for consistency. Documentation directory added for future reference.
This commit is contained in:
Richard R 2026-05-27 06:33:14 -06:00
parent 5de9069c20
commit 3da13c2970
19 changed files with 4 additions and 67 deletions

View file

@ -333,7 +333,6 @@ export async function POST(request: NextRequest) {
if (!existingResult.settings) {
serverLogger.error({
event: 'audiobook.chapter.meta_settings.invalid',
errorCode: 'AUDIOBOOK_CHAPTER_META_SETTINGS_INVALID',
bookId,
storageUserId,
error: {

View file

@ -269,7 +269,6 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string
if (closed) return;
logger.warn({
event: 'documents.parsed.events.db_resync_failed',
errorCode: 'DOCUMENTS_PARSED_EVENTS_DB_RESYNC_FAILED',
degraded: true,
step: 'db_resync',
documentId: id,
@ -347,7 +346,6 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string
const upstreamResponseBody = await response.text().catch(() => '');
logger.warn({
event: 'documents.parsed.events.worker_stream_request_failed',
errorCode: 'DOCUMENTS_PARSED_EVENTS_WORKER_STREAM_REQUEST_FAILED',
degraded: true,
step: 'worker_stream_request',
documentId: id,
@ -365,7 +363,6 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string
if (!response.body) {
logger.warn({
event: 'documents.parsed.events.worker_stream_missing_body',
errorCode: 'DOCUMENTS_PARSED_EVENTS_WORKER_STREAM_MISSING_BODY',
degraded: true,
step: 'worker_stream_body',
documentId: id,
@ -474,7 +471,6 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string
logger.error({
event: 'documents.parsed.events.worker_proxy_crashed',
documentId: id,
errorCode: 'DOCUMENTS_PARSED_EVENTS_WORKER_PROXY_CRASHED',
error: errorToLog(error),
}, 'Worker proxy crashed while streaming parse events');
if (!closed) {
@ -505,7 +501,6 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string
} catch (error) {
logger.error({
event: 'documents.parsed.events.route_failed',
errorCode: 'DOCUMENTS_PARSED_EVENTS_ROUTE_FAILED',
error: errorToLog(error),
}, 'Parsed events route failed');
return NextResponse.json({ error: 'Failed to stream parsed PDF progress' }, { status: 500 });

View file

@ -220,7 +220,6 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string
}
logger.warn({
event: 'documents.parsed.requested_op_unavailable',
errorCode: 'DOCUMENTS_PARSED_REQUESTED_OP_UNAVAILABLE',
degraded: true,
step: 'requested_op_lookup',
documentId: id,
@ -314,7 +313,6 @@ export async function GET(req: NextRequest, ctx: { params: Promise<{ id: string
} catch (error) {
logger.error({
event: 'documents.parsed.get_failed',
errorCode: 'DOCUMENTS_PARSED_GET_FAILED',
error: errorToLog(error),
}, 'Failed to read parsed PDF');
return NextResponse.json({ error: 'Failed to read parsed PDF' }, { status: 500 });
@ -395,7 +393,6 @@ export async function POST(req: NextRequest, ctx: { params: Promise<{ id: string
} catch (error) {
logger.error({
event: 'documents.parsed.force_refresh_failed',
errorCode: 'DOCUMENTS_PARSED_FORCE_REFRESH_FAILED',
error: errorToLog(error),
}, 'Failed to force PDF refresh');
return NextResponse.json({ error: 'Failed to force PDF refresh' }, { status: 500 });

View file

@ -52,7 +52,6 @@ export async function GET(request: NextRequest) {
} catch (error) {
logger.error({
event: 'tts.segments.audio_fallback_failed',
errorCode: 'TTS_SEGMENT_AUDIO_FALLBACK_FAILED',
error: errorToLog(error),
}, 'Failed to load segment audio from fallback route');
return NextResponse.json({ error: 'Failed to load segment audio' }, { status: 500 });

View file

@ -41,7 +41,6 @@ export async function POST(request: NextRequest) {
} catch (error) {
logger.error({
event: 'tts.segments.clear_failed',
errorCode: 'TTS_SEGMENTS_CLEAR_FAILED',
error: errorToLog(error),
}, 'Failed to clear TTS segment cache');
return NextResponse.json({ error: 'Failed to clear TTS segment cache' }, { status: 500 });

View file

@ -423,7 +423,6 @@ export async function POST(request: NextRequest) {
documentId: parsed.documentId,
segmentId: segment.segmentId,
aborted,
errorCode: 'TTS_SEGMENT_ALIGNMENT_UNAVAILABLE',
...(aborted ? {} : { degraded: true }),
step: 'whisper_align',
error: errorToLog(alignError),
@ -668,7 +667,6 @@ export async function POST(request: NextRequest) {
documentId: parsed.documentId,
segmentId: segment.segmentId,
aborted,
errorCode: 'TTS_SEGMENT_ALIGNMENT_UNAVAILABLE',
...(aborted ? {} : { degraded: true }),
step: 'whisper_align',
error: errorToLog(alignError),
@ -720,7 +718,7 @@ export async function POST(request: NextRequest) {
const retryAfterSeconds = upstreamStatus === 429
? getUpstreamRetryAfterSeconds(error)
: undefined;
const errorCode = upstreamStatus === 429
const failureCode = upstreamStatus === 429
? 'UPSTREAM_RATE_LIMIT'
: upstreamStatus && upstreamStatus >= 500
? 'UPSTREAM_TTS_ERROR'
@ -735,7 +733,6 @@ export async function POST(request: NextRequest) {
elapsedMs: Date.now() - segmentStartedAt,
stageTimings,
aborted: true,
errorCode,
error: errorToLog(error),
completedSoFar: manifest.length,
totalRequested: normalized.length,
@ -752,7 +749,6 @@ export async function POST(request: NextRequest) {
aborted: false,
upstreamStatus,
retryAfterSeconds,
errorCode,
error: errorToLog(error),
}, 'TTS segment generation failed');
}
@ -762,7 +758,7 @@ export async function POST(request: NextRequest) {
status: aborted ? 'pending' : 'error',
error: aborted ? null : (
upstreamStatus
? `${errorCode}${retryAfterSeconds ? ` (retry after ${retryAfterSeconds}s)` : ''}: ${errorMessage}`
? `${failureCode}${retryAfterSeconds ? ` (retry after ${retryAfterSeconds}s)` : ''}: ${errorMessage}`
: errorMessage
),
updatedAt: Date.now(),
@ -785,7 +781,7 @@ export async function POST(request: NextRequest) {
error: aborted
? null
: {
code: errorCode,
code: failureCode,
detail: errorMessage,
...(typeof upstreamStatus === 'number' ? { upstreamStatus } : {}),
...(typeof retryAfterSeconds === 'number' ? { retryAfterSeconds } : {}),
@ -804,7 +800,6 @@ export async function POST(request: NextRequest) {
if (errorItems.length > 0) {
logger.error({
event: 'tts.segments.ensure.partial_result',
errorCode: 'TTS_SEGMENT_PARTIAL_FAILURE',
requestId,
documentId: parsed.documentId,
total: manifest.length,
@ -835,7 +830,6 @@ export async function POST(request: NextRequest) {
} catch (error) {
logger.error({
event: 'tts.segments.ensure.route_failed',
errorCode: 'TTS_SEGMENTS_ENSURE_ROUTE_FAILED',
error: errorToLog(error),
}, 'TTS segments ensure route failed');
const response = NextResponse.json({ error: 'Failed to ensure TTS segments' }, { status: 500 });

View file

@ -388,7 +388,6 @@ export async function GET(request: NextRequest) {
} catch (error) {
logger.error({
event: 'tts.segments.manifest.list_failed',
errorCode: 'TTS_SEGMENTS_MANIFEST_LIST_FAILED',
error: errorToLog(error),
}, 'Failed to list TTS segments');
return NextResponse.json({ error: 'Failed to list TTS segments' }, { status: 500 });

View file

@ -63,7 +63,6 @@ export async function syncAdminFlag(
} catch (error) {
serverLogger.warn({
event: 'admin.email_sync.user_flag_update.failed',
errorCode: 'ADMIN_EMAIL_SYNC_USER_FLAG_UPDATE_FAILED',
userIdHash: hashForLog(userId),
degraded: true,
error: errorToLog(error),

View file

@ -33,7 +33,6 @@ export async function ensureAdminSeed(): Promise<void> {
seedPromise = runSeed().catch((error) => {
serverLogger.warn({
event: 'admin.seed.run.failed',
errorCode: 'ADMIN_SEED_RUN_FAILED',
degraded: true,
error: errorToLog(error),
}, 'Admin seed run failed');
@ -66,7 +65,6 @@ async function seedDefaultAdminProvider(): Promise<void> {
} catch (error) {
serverLogger.warn({
event: 'admin.seed.providers.check_failed',
errorCode: 'ADMIN_SEED_PROVIDERS_CHECK_FAILED',
degraded: true,
error: errorToLog(error),
}, 'Could not check admin_providers');
@ -104,7 +102,6 @@ async function seedDefaultAdminProvider(): Promise<void> {
} catch (fallbackError) {
serverLogger.warn({
event: 'admin.seed.restrict_user_api_keys.fallback_write_failed',
errorCode: 'ADMIN_SEED_RESTRICT_USER_API_KEYS_FALLBACK_WRITE_FAILED',
degraded: true,
error: errorToLog(fallbackError),
}, 'Failed to write restrictUserApiKeys fallback after encryption failure');
@ -112,7 +109,6 @@ async function seedDefaultAdminProvider(): Promise<void> {
}
serverLogger.warn({
event: 'admin.seed.provider_key_encrypt.failed',
errorCode: 'ADMIN_SEED_PROVIDER_KEY_ENCRYPT_FAILED',
degraded: true,
error: errorToLog(error),
}, 'Failed to encrypt default provider API key');
@ -141,7 +137,6 @@ async function seedDefaultAdminProvider(): Promise<void> {
} catch (error) {
serverLogger.warn({
event: 'admin.seed.provider_insert.failed',
errorCode: 'ADMIN_SEED_PROVIDER_INSERT_FAILED',
degraded: true,
providerSlug: 'default-openai',
error: errorToLog(error),
@ -171,7 +166,6 @@ async function cleanupLegacyDefaultTtsProviderSeedRow(): Promise<void> {
} catch (error) {
serverLogger.warn({
event: 'admin.seed.legacy_default_provider_cleanup.failed',
errorCode: 'ADMIN_SEED_LEGACY_DEFAULT_PROVIDER_CLEANUP_FAILED',
degraded: true,
error: errorToLog(error),
}, 'Failed to cleanup legacy defaultTtsProvider seed row');
@ -186,7 +180,6 @@ async function cleanupLegacyDefaultTtsModelRows(): Promise<void> {
} catch (error) {
serverLogger.warn({
event: 'admin.seed.legacy_default_model_cleanup.failed',
errorCode: 'ADMIN_SEED_LEGACY_DEFAULT_MODEL_CLEANUP_FAILED',
degraded: true,
error: errorToLog(error),
}, 'Failed to cleanup legacy defaultTtsModel rows');

View file

@ -116,7 +116,6 @@ async function resolveImplicitDefaultTtsProvider(): Promise<string | undefined>
} catch (error) {
serverLogger.warn({
event: 'admin.runtime_config.default_provider_lookup.failed',
errorCode: 'ADMIN_RUNTIME_CONFIG_DEFAULT_PROVIDER_LOOKUP_FAILED',
degraded: true,
error: errorToLog(error),
}, 'Implicit defaultTtsProvider lookup failed');
@ -149,7 +148,6 @@ async function readAllRows(): Promise<Map<string, { value: unknown; source: stri
} catch (error) {
serverLogger.warn({
event: 'admin.runtime_config.read.failed',
errorCode: 'ADMIN_RUNTIME_CONFIG_READ_FAILED',
degraded: true,
error: errorToLog(error),
}, 'Runtime config read failed');
@ -310,7 +308,6 @@ export async function seedRuntimeConfigFromEnv(): Promise<{ seeded: RuntimeConfi
} catch (error) {
serverLogger.warn({
event: 'admin.runtime_config.seed.failed',
errorCode: 'ADMIN_RUNTIME_CONFIG_SEED_FAILED',
degraded: true,
key,
error: errorToLog(error),

View file

@ -96,7 +96,6 @@ const createAuth = () => betterAuth({
} catch (error) {
serverLogger.warn({
event: 'auth.user_delete.storage_cleanup_failed',
errorCode: 'AUTH_USER_DELETE_STORAGE_CLEANUP_FAILED',
degraded: true,
step: 'delete_user_storage',
userIdHash: hashForLog(user.id),
@ -180,7 +179,6 @@ const createAuth = () => betterAuth({
} catch (error) {
serverLogger.warn({
event: 'auth.link_account.transfer.rate_limit.failed',
errorCode: 'AUTH_LINK_ACCOUNT_TRANSFER_RATE_LIMIT_FAILED',
degraded: true,
step: 'transfer_rate_limit',
anonymousUserIdHash: hashForLog(anonymousUser.user.id),
@ -204,7 +202,6 @@ const createAuth = () => betterAuth({
} catch (error) {
serverLogger.warn({
event: 'auth.link_account.transfer.audiobooks.failed',
errorCode: 'AUTH_LINK_ACCOUNT_TRANSFER_AUDIOBOOKS_FAILED',
degraded: true,
step: 'transfer_audiobooks',
anonymousUserIdHash: hashForLog(anonymousUser.user.id),
@ -228,7 +225,6 @@ const createAuth = () => betterAuth({
} catch (error) {
serverLogger.warn({
event: 'auth.link_account.transfer.documents.failed',
errorCode: 'AUTH_LINK_ACCOUNT_TRANSFER_DOCUMENTS_FAILED',
degraded: true,
step: 'transfer_documents',
anonymousUserIdHash: hashForLog(anonymousUser.user.id),
@ -252,7 +248,6 @@ const createAuth = () => betterAuth({
} catch (error) {
serverLogger.warn({
event: 'auth.link_account.transfer.preferences.failed',
errorCode: 'AUTH_LINK_ACCOUNT_TRANSFER_PREFERENCES_FAILED',
degraded: true,
step: 'transfer_preferences',
anonymousUserIdHash: hashForLog(anonymousUser.user.id),
@ -276,7 +271,6 @@ const createAuth = () => betterAuth({
} catch (error) {
serverLogger.warn({
event: 'auth.link_account.transfer.progress.failed',
errorCode: 'AUTH_LINK_ACCOUNT_TRANSFER_PROGRESS_FAILED',
degraded: true,
step: 'transfer_progress',
anonymousUserIdHash: hashForLog(anonymousUser.user.id),
@ -288,7 +282,6 @@ const createAuth = () => betterAuth({
} catch (error) {
serverLogger.error({
event: 'auth.link_account.failed',
errorCode: 'AUTH_LINK_ACCOUNT_FAILED',
error: errorToLog(error),
}, 'onLinkAccount callback failed');
// Don't throw here to prevent blocking the account linking process

View file

@ -16,7 +16,6 @@ export async function fetchWorkerOperationState<Result>(
} catch (error) {
serverLogger.warn({
event: 'compute.worker_op_state.config.invalid',
errorCode: 'COMPUTE_WORKER_OP_STATE_CONFIG_INVALID',
opId: normalized,
degraded: true,
step: 'read_worker_config',
@ -43,7 +42,6 @@ export async function fetchWorkerOperationState<Result>(
const upstreamResponseBody = await res.text().catch(() => '');
serverLogger.warn({
event: 'compute.worker_op_state.fetch.failed',
errorCode: 'COMPUTE_WORKER_OP_STATE_FETCH_FAILED',
opId: normalized,
status: res.status,
upstreamResponseBody,
@ -60,7 +58,6 @@ export async function fetchWorkerOperationState<Result>(
if (!parsed || typeof parsed !== 'object' || parsed.opId !== normalized) {
serverLogger.warn({
event: 'compute.worker_op_state.response.invalid',
errorCode: 'COMPUTE_WORKER_OP_STATE_RESPONSE_INVALID',
opId: normalized,
degraded: true,
step: 'validate_worker_op_response',
@ -71,7 +68,6 @@ export async function fetchWorkerOperationState<Result>(
} catch (error) {
serverLogger.warn({
event: 'compute.worker_op_state.fetch.error',
errorCode: 'COMPUTE_WORKER_OP_STATE_FETCH_ERROR',
opId: normalized,
degraded: true,
step: 'fetch_worker_op',

View file

@ -300,7 +300,6 @@ export class WorkerComputeBackend implements ComputeBackend {
return { alignments: final.result.alignments };
}, ({ attempt, maxAttempts, willRetry, delayMs, error }) => {
logWorker(willRetry ? 'warn' : 'error', 'align.request.attempt_error', {
errorCode: 'COMPUTE_WORKER_ALIGN_REQUEST_ATTEMPT_ERROR',
traceId,
kind: 'whisper_align',
opKeyHash,
@ -321,7 +320,6 @@ export class WorkerComputeBackend implements ComputeBackend {
return result;
} catch (error) {
logWorker('error', 'align.request.failed', {
errorCode: 'COMPUTE_WORKER_ALIGN_REQUEST_FAILED',
traceId,
kind: 'whisper_align',
opKeyHash,
@ -400,7 +398,6 @@ export class WorkerComputeBackend implements ComputeBackend {
throw new Error('PDF layout worker operation completed without parsed output');
}, ({ attempt, maxAttempts, willRetry, delayMs, error }) => {
logWorker(willRetry ? 'warn' : 'error', 'pdf_layout.request.attempt_error', {
errorCode: 'COMPUTE_WORKER_PDF_LAYOUT_REQUEST_ATTEMPT_ERROR',
traceId,
kind: 'pdf_layout',
opKeyHash,
@ -423,7 +420,6 @@ export class WorkerComputeBackend implements ComputeBackend {
return result;
} catch (error) {
logWorker('error', 'pdf_layout.request.failed', {
errorCode: 'COMPUTE_WORKER_PDF_LAYOUT_REQUEST_FAILED',
traceId,
kind: 'pdf_layout',
opKeyHash,
@ -468,7 +464,6 @@ export class WorkerComputeBackend implements ComputeBackend {
retryAfterMs,
);
logWorker(res.status >= 500 ? 'warn' : 'error', 'http.request.failed', {
errorCode: 'COMPUTE_WORKER_HTTP_REQUEST_FAILED',
...context,
traceId,
method,
@ -547,7 +542,6 @@ export class WorkerComputeBackend implements ComputeBackend {
retryAfterMs,
);
logWorker(res.status >= 500 ? 'warn' : 'error', 'sse.wait.http_failed', {
errorCode: 'COMPUTE_WORKER_SSE_WAIT_HTTP_FAILED',
...context,
traceId,
opId,
@ -669,7 +663,6 @@ export class WorkerComputeBackend implements ComputeBackend {
}
logWorker('error', 'sse.wait.ended_without_terminal', {
errorCode: 'COMPUTE_WORKER_SSE_WAIT_ENDED_WITHOUT_TERMINAL',
...context,
traceId,
opId,
@ -684,7 +677,6 @@ export class WorkerComputeBackend implements ComputeBackend {
throw new Error(`Operation stream ended before terminal state for op ${opId}`);
} catch (error) {
logWorker('error', 'sse.wait.failed', {
errorCode: 'COMPUTE_WORKER_SSE_WAIT_FAILED',
...context,
traceId,
opId,

View file

@ -377,7 +377,6 @@ export async function ensureDocumentPreview(doc: PreviewSourceDocument, namespac
} catch (error) {
serverLogger.error({
event: 'documents.preview.generate.failed',
errorCode: 'DOCUMENTS_PREVIEW_GENERATE_FAILED',
documentId: doc.id,
documentType: doc.type,
error: errorToLog(error),

View file

@ -390,7 +390,6 @@ export async function parsePdfJob(input: UserPdfLayoutJobRequest): Promise<void>
} catch (statusError) {
serverLogger.error({
event: 'documents.parse.status_write.failed',
errorCode: 'DOCUMENTS_PARSE_STATUS_WRITE_FAILED',
documentId: input.documentId,
parseStatus,
error: errorToLog(statusError),
@ -398,7 +397,6 @@ export async function parsePdfJob(input: UserPdfLayoutJobRequest): Promise<void>
}
serverLogger.error({
event: 'documents.parse.job.failed',
errorCode: 'DOCUMENTS_PARSE_JOB_FAILED',
documentId: input.documentId,
parseStatus,
error: errorToLog(error),
@ -415,7 +413,6 @@ export function enqueueParsePdfJob(input: UserPdfLayoutJobRequest): void {
serverLogger.error({
event: 'documents.parse.job.uncaught_error',
documentId: input.documentId,
errorCode: 'DOCUMENTS_PARSE_JOB_UNCAUGHT_ERROR',
error: errorToLog(error),
}, 'Parse job uncaught error');
});

View file

@ -17,7 +17,6 @@ export type ServerErrorClass =
| 'unknown';
export type ServerErrorContract = {
errorCode: string;
errorClass: ServerErrorClass;
retryable: boolean;
httpStatus: number;
@ -28,7 +27,6 @@ export type ServerErrorContract = {
export type ServerApiErrorBody = {
error: string;
errorCode: string;
retryable?: boolean;
details?: Record<string, unknown>;
};
@ -144,11 +142,10 @@ export function errorToLog(error: unknown, depth = 0): LoggedError {
}
export function apiErrorBody(
input: Omit<ServerApiErrorBody, 'errorCode'> & { errorCode: string },
input: ServerApiErrorBody,
): ServerApiErrorBody {
return {
error: input.error,
errorCode: input.errorCode,
...(typeof input.retryable === 'boolean' ? { retryable: input.retryable } : {}),
...(input.details ? { details: input.details } : {}),
};

View file

@ -68,7 +68,6 @@ export async function clearTtsSegmentCache(
warning = error instanceof Error ? error.message : 'Failed deleting some audio objects';
serverLogger.warn({
event: 'tts.segments.cache.audio_cleanup_failed',
errorCode: 'TTS_SEGMENTS_CACHE_AUDIO_CLEANUP_FAILED',
degraded: true,
step: 'delete_tts_audio_objects',
documentId: input.documentId,

View file

@ -195,7 +195,6 @@ async function fetchReplicateOpenApiSchema(apiKey: string, model: string): Promi
}
serverLogger.error({
event: 'tts.voice_resolution.replicate_schema_fetch.failed',
errorCode: 'TTS_VOICE_RESOLUTION_REPLICATE_SCHEMA_FETCH_FAILED',
error: errorToLog(error),
}, 'Failed fetching Replicate model schema');
return null;
@ -290,7 +289,6 @@ async function fetchDeepinfraVoices(apiKey: string): Promise<string[]> {
}
serverLogger.error({
event: 'tts.voice_resolution.deepinfra_voices_fetch.failed',
errorCode: 'TTS_VOICE_RESOLUTION_DEEPINFRA_VOICES_FETCH_FAILED',
error: errorToLog(error),
}, 'Failed fetching Deepinfra voices');
return [];

View file

@ -52,7 +52,6 @@ export async function deleteUserStorageData(
} catch (error) {
serverLogger.warn({
event: 'user.data_cleanup.document_blob_delete.failed',
errorCode: 'USER_DATA_CLEANUP_DOCUMENT_BLOB_DELETE_FAILED',
degraded: true,
step: 'delete_document_blob',
documentId: doc.id,
@ -66,7 +65,6 @@ export async function deleteUserStorageData(
} catch (error) {
serverLogger.warn({
event: 'user.data_cleanup.document_preview_delete.failed',
errorCode: 'USER_DATA_CLEANUP_DOCUMENT_PREVIEW_DELETE_FAILED',
degraded: true,
step: 'delete_document_preview_artifacts',
documentId: doc.id,
@ -82,7 +80,6 @@ export async function deleteUserStorageData(
} catch (error) {
serverLogger.warn({
event: 'user.data_cleanup.document_preview_rows_delete.failed',
errorCode: 'USER_DATA_CLEANUP_DOCUMENT_PREVIEW_ROWS_DELETE_FAILED',
degraded: true,
step: 'delete_document_preview_rows',
documentId: doc.id,
@ -109,7 +106,6 @@ export async function deleteUserStorageData(
} catch (error) {
serverLogger.warn({
event: 'user.data_cleanup.audiobook_blobs_delete.failed',
errorCode: 'USER_DATA_CLEANUP_AUDIOBOOK_BLOBS_DELETE_FAILED',
degraded: true,
step: 'delete_audiobook_prefix',
bookId: book.id,
@ -132,7 +128,6 @@ export async function deleteUserStorageData(
} catch (error) {
serverLogger.warn({
event: 'user.data_cleanup.tts_segments_delete.failed',
errorCode: 'USER_DATA_CLEANUP_TTS_SEGMENTS_DELETE_FAILED',
degraded: true,
step: 'delete_tts_segment_prefixes',
userIdHash: hashForLog(userId),