yikart/AiToEarn · error · AppException
ChannelAccessTokenFailed
ChannelAccessTokenFailed
Error message
ResponseCode.ChannelAccessTokenFailed
What it means
toCredentialContext throws ChannelAccessTokenFailed (AppException, ResponseCode.ChannelAccessTokenFailed) when a CredentialResult obtained from a platform integration during the auth callback has an empty/missing accessToken. It is a defensive boundary between the platform integration result and the CredentialContext used to persist credentials — an integration returned success-shaped data without a token, which must never be stored.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/auth/auth.service.ts:793
source: string,
): Promise<void> {
await this.eventStream.emit(
EventStream.Channels,
EventTopic.ChannelsAccountConnected,
{ userId, accountId, platform },
{ source },
)
}
private shouldReassignDouyinAccount(source: string, platform: AccountType, credential: CredentialResult) {
return source === 'auth'
&& platform === AccountType.Douyin
&& credential.callbackResponseType === AuthCallbackResponseType.Json
}
private toCredentialContext(credential: CredentialResult): CredentialContext {
if (!credential.accessToken) {
throw new AppException(ResponseCode.ChannelAccessTokenFailed)
}
return {
accessToken: credential.accessToken,
refreshToken: credential.refreshToken,
expiresAt: credential.expiresAt,
scope: credential.scope,
platformUid: credential.platformUid,
}
}
getPlatformAuthViewFields(platform: AccountType): Pick<AuthViewFields, 'platformDisplayName' | 'platformLogoUrl'> {
const integration = this.registry.get(platform)
const locale = getLocale()
return {
platformDisplayName: integration.metadata.displayName[locale],
platformLogoUrl: integration.metadata.logoUrl,
}View on GitHub (pinned to d3aa8bea5b)
Solutions
- Inspect the integration's token-exchange code and log the raw platform response to see why accessToken is missing.
- Verify the OAuth app's redirect URI, client id/secret, and callbackResponseType config match the platform console settings.
- Update the platform integration if the provider changed its token response format (API version drift).
- Catch this at the callback layer and return a clear 'authorization failed, please retry' to the user rather than persisting partial credentials.
Example fix
// before
const ctx = toCredentialContext(credential) // throws ChannelAccessTokenFailed
// after
if (!credential.accessToken) {
throw new AppException(ResponseCode.ChannelAccessTokenFailed, { platform, raw: rawResponse })
}
const ctx = toCredentialContext(credential) Defensive patterns
Strategy: validation
Validate before calling
if (!credential || typeof credential.accessToken !== 'string' || credential.accessToken.length === 0) {
throw new AppException(ResponseCode.ChannelAccessTokenFailed, { platform })
} Type guard
function hasAccessToken(c: unknown): c is { accessToken: string } {
return !!c && typeof (c as any).accessToken === 'string' && (c as any).accessToken.length > 0
} Try / catch
try {
await completeAuth(sessionId, credential)
} catch (e) {
if (e instanceof AppException && e.code === ResponseCode.ChannelAccessTokenFailed) {
return res.status(502).json({ message: 'Authorization failed at the platform, please retry' })
}
throw e
} Prevention
- Log raw platform token-exchange responses (redacted) to detect payload changes early.
- Validate OAuth callback query params (code, state) before exchanging.
- Pin/verify platform OAuth API versions and review provider changelogs.
- Add contract tests per integration asserting accessToken is present for a happy-path exchange.
When it happens
Trigger: A channel integration's auth callback parsing produces a CredentialResult with no accessToken (platform returned an error payload the integration didn't map, mis-parsed response body, callbackResponseType mismatch e.g. expecting Json but receiving a redirect, or truncated query params in the OAuth redirect).
Common situations: Platform changed its OAuth callback payload shape after an API version update; wrong redirect URI config causing the code exchange to return an error body; Douyin/WeChat returning error codes the integration ignores; testing with a stub integration that returns partial credentials.
Related errors
- ResponseCode.ChannelAccountNotAuthorized
- No response from Gemini
- ResponseCode.ChannelAuthSessionInvalid
- ResponseCode.ChannelAuthPlatformMismatch
- ResponseCode.ChannelAuthSessionCompleted
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/cd5d4684aefb806b.
Report an issue: GitHub.