yikart/AiToEarn · error · BadRequestException

YouTube API请求失败

Error message

YouTube API请求失败

What it means

The handler's fallback: if error.response is absent (network failure, timeout, DNS error, request never reached Google) or status is 401/403 with no parsable body and no data.error.message, the service throws BadRequestException('YouTube API请求失败'). It's the catch-all meaning 'the call failed for an unclassified reason'.

Source

Thrown at project/aitoearn-electron/server/src/modules/plat/youtube/youtube.service.ts:1312

   * 处理API错误
   * @param error 错误对象
   */
  private handleApiError(error: any) {
    console.error('YouTube API Error:', error);

    if (error.response) {
      // API响应错误
      const { status, data } = error.response;
      if (status === 401) {
        throw new BadRequestException('授权已过期,请重新授权');
      } else if (status === 403) {
        throw new BadRequestException('权限不足,无法执行此操作');
      } else if (data && data.error && data.error.message) {
        throw new BadRequestException(`YouTube API错误: ${data.error.message}`);
      }
    }

    throw new BadRequestException('YouTube API请求失败');
  }

}

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Log the raw error (error.code, error.cause, error.message) — absence of error.response means the request never completed.
  2. Check outbound network/DNS/proxy access to www.googleapis.com:443 from the server.
  3. Add timeouts and classify ECONNABORTED/ENOTFOUND/EAI_AGAIN codes distinctly from API errors.
  4. Ensure the axios error is actually passed to this handler (not swallowed or wrapped elsewhere).
  5. Implement retry with exponential backoff for transient network codes.

Example fix

// before
console.error('YouTube API Error:', error);
// after
if (!error.response) {
  console.error('Network-level failure:', { code: error.code, message: error.message, cause: error.cause });
  throw new BadRequestException(`YouTube 网络请求失败: ${error.code ?? 'UNKNOWN'}`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

const reachable = await fetch('https://www.googleapis.com/discovery/v1/apis', { signal: AbortSignal.timeout(5000) }).then(r => r.ok).catch(() => false);
if (!reachable) throw new Error('googleapis.com unreachable from this host');

Type guard

function isNetworkError(e: unknown): boolean {
  const anyE = e as any;
  return !anyE?.response && ['ECONNREFUSED','ETIMEDOUT','ECONNRESET','ENOTFOUND','EAI_AGAIN','ECONNABORTED'].includes(anyE?.code ?? '');
}

Try / catch

try {
  return await callYouTubeApi();
} catch (e) {
  if (isNetworkError(e)) {
    await sleep(backoff(attempt)); // retry with exponential backoff up to N times
    return callYouTubeApi();
  }
  throw e;
}

Prevention

When it happens

Trigger: error.response is undefined: connection refused/timeout, proxy blocking googleapis.com, ECONNRESET, TLS issues, or offline server; also 401/403 responses whose body lacks error.error.message fall through here.

Common situations: Corporate proxy/firewall blocking outbound HTTPS to www.googleapis.com; server in a region without YouTube API access; DNS misconfiguration; axios misconfiguration (no adapter/timeout); error object not an AxiosError at all.

Related errors


AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31). Data as JSON: /api/errors/0f067415b5825665. Report an issue: GitHub.