{"record":{"id":"76cec645601550c9","repo":"yikart/AiToEarn","slug":"15070-76cec6","errorCode":"15070","errorMessage":"{{platform}} platform API request failed","messagePattern":"(.+?)\\} platform API request failed","errorType":"exception","errorClass":"TikTokPlatformException","httpStatus":null,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/tiktok/tiktok.service.ts","lineNumber":56,"sourceCode":"    private readonly mediaService: MediaService,\n  ) {\n    this.http = this.createHttpClient()\n  }\n\n  private readonly apiBaseUrl = 'https://open.tiktokapis.com/v2'\n  private readonly authUrl = 'https://www.tiktok.com/v2/auth/authorize'\n\n  private createHttpClient(): AxiosInstance {\n    const http = axios.create()\n    http.interceptors.response.use(\n      (response) => {\n        if (TikTokPlatformException.hasPlatformError(response)) {\n          throw TikTokPlatformException.fromPlatformResponse(response)\n        }\n        return response\n      },\n      (error: AxiosError<TikTokPlatformResponseBody>) => {\n        throw TikTokPlatformException.fromAxiosError(error)\n      },\n    )\n    return http\n  }\n\n  private async apiRequest<T>(\n    url: string,\n    options: TikTokRequestOptions = {},\n    accessToken?: string,\n  ): Promise<T> {\n    const headers: Record<string, string> = accessToken\n      ? {\n          ...(options.headers ?? {}),\n          'Authorization': `Bearer ${accessToken}`,\n          'Content-Type': 'application/json; charset=UTF-8',\n        }\n      : {\n          ...(options.headers ?? {}),","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/tiktok/tiktok.service.ts#L38-L74","documentation":"TikTokService.createHttpClient() installs a response interceptor on the shared Axios instance; every error response (or network failure) from open.tiktokapis.net is rethrown as TikTokPlatformException.fromAxiosError with code ChannelPlatformApiFailed (15070). The code is specialized by endpoint (/oauth/ -> ChannelAccessTokenFailed, /upload/ and /post/publish/ -> ChannelPlatformMediaProcessingFailed) and by any error code present in the TikTok response body.","triggerScenarios":"Any TikTok Open API call through the constructed client fails: non-2xx HTTP response, TikTok body containing error.code (e.g. access_token_invalid, rate_limit_exceeded, invalid_params), OAuth token endpoint failures, or axios network errors (timeout, DNS, connection refused).","commonSituations":"Expired TikTok access token (tokens last 24h; refresh token 365d); missing tiktok.trial.publish or video.upload scopes for unreviewed apps; client_key/client_secret misconfigured; upload endpoints hit before chunk completion; corporate proxy blocking open.tiktokapis.net.","solutions":["Read exception.cause.platformCode/httpStatus to get TikTok's specific error code and message","For access_token_invalid, use the refresh token to obtain a new access token before retrying","For upload/publish endpoints, confirm the file upload completed and check CATEGORY is ChannelPlatformMediaProcessingFailed","Verify app scopes and audit status (unreviewed apps can only post SELF_ONLY)","If retryable=true, retry with backoff; otherwise fix app config or parameters"],"exampleFix":"// before\nconst res = await this.http.post(url, body) // interceptor throws 15070\n// after\ntry {\n  const res = await this.http.post(url, body)\n} catch (e) {\n  if (e instanceof ChannelPlatformException && e.cause?.platformCode === 'access_token_invalid') {\n    await this.refreshAccessToken(account)\n    return this.http.post(url, body)\n  }\n  throw e\n}","handlingStrategy":"try-catch","validationCode":"if (!account.accessToken || account.tokenExpiresAt <= new Date()) await refreshTikTokToken(account)","typeGuard":"function isTikTokPlatformException(e: unknown): e is TikTokPlatformException {\n  return e instanceof TikTokPlatformException\n}","tryCatchPattern":"try {\n  const res = await this.http.post(url, body)\n} catch (e) {\n  if (e instanceof TikTokPlatformException) {\n    const code = e.cause?.platformCode\n    if (code === 'access_token_invalid') return refreshAndRetry()\n    if (e.retryable) return retryWithBackoff()\n  }\n  throw e\n}","preventionTips":["Refresh TikTok access tokens proactively (24h lifetime)","Confirm app scopes include video.upload / video.publish and the app passed review for public posting","Match on cause.platformCode rather than the generic 15070 code","Apply backoff on retryable errors and rate-limit-aware scheduling","Keep client_key/client_secret in config, not hard-coded, and verify per environment"],"tags":["tiktok","axios","interceptor","oauth","platform-integration"],"backgroundTag":"platform-api-request-failed","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}