yikart/AiToEarn · error · AppException

ChannelAuthCodeMissing

ChannelAuthCodeMissing

Error message

ResponseCode.ChannelAuthCodeMissing

What it means

Thrown in parseMiniAppCallback when the callback payload fails schema validation on the 'token' field, i.e. the authorization code/token from Douyin is absent or invalid. Distinct from CSRF failure: the session state is fine but there is no usable auth token to exchange.

Source

Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/douyin/douyin-auth.provider.ts:241

      state: input.query?.state ?? input.body?.state,
      token: input.query?.token ?? input.body?.token,
      nickname: input.query?.nickname ?? input.body?.nickname,
      avatar: input.query?.avatar ?? input.body?.avatar,
      tickets: input.body?.tickets,
    }
    if (payload.token === undefined && payload.tickets === undefined) {
      return undefined
    }

    const result = DouyinMiniAppCallbackSchema.safeParse(payload)
    if (!result.success) {
      const hasInvalidState = result.error.issues.some(issue => issue.path[0] === 'state')
      const hasInvalidToken = result.error.issues.some(issue => issue.path[0] === 'token')
      if (hasInvalidState) {
        throw new AppException(ResponseCode.ChannelAuthCsrfInvalid)
      }
      if (hasInvalidToken) {
        throw new AppException(ResponseCode.ChannelAuthCodeMissing)
      }

      throw new AppException(ResponseCode.ChannelAuthorizationFailed)
    }

    assertParsedCallbackState(result.data.state, input.session.id)
    return result.data
  }

  private hasMiniAppScope(scopes: string | undefined, scope: string) {
    return !!scopes?.split(/[,\s]+/).includes(scope)
  }

  private maskOpenId(openId: string) {
    if (openId.length <= 8) {
      return openId
    }

View on GitHub (pinned to d3aa8bea5b)

Solutions

  1. Have the user restart the mini-app authorization so Douyin issues a fresh token
  2. Inspect the raw callback payload to confirm the token parameter name/value matches the schema
  3. Check the frontend callback handler isn't stripping or renaming the token param before calling the backend
Defensive patterns

Strategy: validation

Validate before calling

const token = callbackPayload?.token
if (typeof token !== 'string' || token.length === 0) {
  throw new Error('Authorization callback is missing the token/code parameter')
}

Type guard

function hasAuthCode(payload: unknown): payload is { token: string } {
  return typeof payload === 'object' && payload !== null && typeof (payload as any).token === 'string' && (payload as any).token.length > 0
}

Try / catch

try {
  await provider.miniAppCallback(payload)
} catch (e) {
  if (e instanceof AppException && e.code === 'ChannelAuthCodeMissing') {
    return { restartAuth: true, message: 'No authorization token received; please authorize again' }
  }
  throw e
}

Prevention

When it happens

Trigger: Douyin mini-app callback where 'token' (the auth code field) is missing, empty, or of the wrong type per DouyinMiniAppCallbackSchema.

Common situations: User landed on the callback page without completing authorization, Douyin returned an error code instead of a token, frontend dropped the token query parameter, or the callback URL was visited directly.

Related errors


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