yikart/AiToEarn · error · AppException

ChannelPlatformResponseInvalid

ChannelPlatformResponseInvalid

Error message

ChannelPlatformResponseInvalid

What it means

ChannelPlatformResponseInvalid is thrown by DouyinOfflineQrService.createPublish when the handoff publish result from the Douyin publish provider is incomplete: platformWorkId, dataOption.schema, dataOption.shortLink, or dataOption.expiresAt is missing after parseDouyinDataOption. The offline-QR flow requires all four fields to build a scannable, expiring QR share record, so any missing piece invalidates the whole response.

Source

Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/douyin/offline-qr/douyin-offline-qr.service.ts:33

  constructor(
    private readonly publishRecordRepo: PublishRecordRepository,
    private readonly materialGroupRepo: MaterialGroupRepository,
    private readonly materialRepo: MaterialRepository,
    private readonly douyinPublishProvider: DouyinPublishProvider,
    private readonly mediaService: MediaService,
  ) {}

  async createPublish(dto: CreateDouyinOfflineQrPublishDto) {
    await this.validateMaterial(dto.materialGroupId, dto.materialId)
    const content = await this.prepareContent(dto.content)

    const result = await this.douyinPublishProvider.createHandoffPublishResult({
      content,
      option: dto.option,
    })
    const dataOption = parseDouyinDataOption(result.dataOption)
    if (!result.platformWorkId || !dataOption?.schema || !dataOption.shortLink || !dataOption.expiresAt) {
      throw new AppException(ResponseCode.ChannelPlatformResponseInvalid, { platform: AccountType.Douyin })
    }

    const type = this.resolvePublishType(content)
    const media = this.resolveRecordMedia(content, type)
    const record = await this.publishRecordRepo.create({
      userId: '',
      accountId: '',
      uid: '',
      materialGroupId: dto.materialGroupId,
      materialId: dto.materialId,
      accountType: AccountType.Douyin,
      type,
      status: PublishStatus.WaitingForUserAction,
      title: content.title,
      desc: content.body,
      topics: parseTopicsFromBody(content.body),
      publishTime: new Date(),
      source: dto.source ?? PublishRecordSource.OfflineQr,

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Log the raw provider result and check which field is missing (platformWorkId vs schema vs shortLink vs expiresAt) to target the real failure.
  2. Verify the Douyin app has share/schema permissions and valid client credentials so generateShareSchema produces a full schema URL.
  3. Confirm parseDouyinDataOption still matches the current Douyin dataOption format (update after platform API changes).
  4. Retry the createPublish call; transient upstream share-id failures often succeed on a second attempt.

Example fix

// before
const result = await provider.createHandoffPublishResult(...) // dataOption lacks expiresAt -> throws
// after
// ensure upstream returns full schema with expiry
const schema = await douyinService.generateShareSchema({ shareId, private_status: 0 })
// provider now returns dataOption.schema/shortLink/expiresAt -> createPublish succeeds
Defensive patterns

Strategy: try-catch

Type guard

function isValidHandoffResult(r: { platformWorkId?: string; dataOption?: unknown } | null)
  : r is { platformWorkId: string; dataOption: { schema: string; shortLink: string; expiresAt: unknown } } {
  const d = parseDouyinDataOption(r?.dataOption)
  return !!r?.platformWorkId && !!d?.schema && !!d?.shortLink && d?.expiresAt != null
}

Try / catch

try {
  const record = await offlineQrService.createPublish(dto)
} catch (err) {
  if (err instanceof AppException && err.code === ResponseCode.ChannelPlatformResponseInvalid) {
    // log raw provider result for which field was missing, retry once before surfacing
  } else throw err
}

Prevention

When it happens

Trigger: Calling createPublish on the offline-QR service when the underlying Douyin share handoff (getShareid/generateShareSchema chain) yields a result whose dataOption cannot be parsed or lacks schema/shortLink/expiresAt — e.g. the share-id request failed upstream, or the schema URL generation returned an empty/short form.

Common situations: Douyin platform returning degraded share-id data; app credentials valid but share schema permission missing so schema generation is skipped; changes in Douyin's dataOption format breaking parseDouyinDataOption; transient upstream failure cached and surfaced here.

Related errors


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