yikart/AiToEarn · error · AppException
ChannelAuthRefreshTokenMissing
ChannelAuthRefreshTokenMissing
Error message
ChannelAuthRefreshTokenMissing
What it means
TikTok credential refresh requires a stored refresh token; refresh() immediately throws ChannelAuthRefreshTokenMissing when input.refreshToken is absent. Without it there is no way to obtain a new access token from TikTok's OAuth endpoint.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/tiktok/tiktok-auth.provider.ts:72
const callback = parseOAuthCallback(input)
const codeVerifier = parseAuthCodeVerifier(input)
const result = await this.tikTokService.exchangeCode(
callback.code,
codeVerifier,
)
return {
accessToken: result.accessToken,
refreshToken: result.refreshToken,
expiresAt: result.expiresAt,
scope: result.scope,
tokenType: 'Bearer',
}
}
async refresh(input: RefreshCredentialInput): Promise<CredentialResult> {
if (!input.refreshToken) {
throw new AppException(ResponseCode.ChannelAuthRefreshTokenMissing)
}
const result = await this.tikTokService.refreshAccessToken(input.refreshToken)
return {
accessToken: result.accessToken,
refreshToken: result.refreshToken,
expiresAt: result.expiresAt,
scope: result.scope,
tokenType: 'Bearer',
}
}
async revoke(input: RevokeCredentialInput): Promise<void> {
await this.tikTokService.revokeAccessToken(input.accessToken)
}
async getProfile(input: CredentialContext): Promise<PlatformAccountProfile> {View on GitHub (pinned to d3aa8bea5b)
Solutions
- Check the stored credential record for the TikTok account — if refreshToken is empty, re-run the TikTok OAuth connect flow to obtain and persist a new refresh token.
- Fix the connect/exchange path so refresh_token from TikTok's token response is always persisted alongside accessToken.
- Skip accounts without refresh tokens in the refresh job instead of throwing, and flag them for re-authorization.
- Verify no migration/cleanup deleted the refreshToken column or field.
Example fix
// before
await authProvider.refresh({ refreshToken: account.credentials.refreshToken })
// after
if (!account.credentials.refreshToken) {
await markAccountNeedsReauth(account.id) // skip refresh, require reconnect
} else {
await authProvider.refresh({ refreshToken: account.credentials.refreshToken })
} Defensive patterns
Strategy: validation
Validate before calling
function canRefresh(creds: TikTokCredentials): boolean {
return typeof creds.refreshToken === 'string' && creds.refreshToken.length > 0
}
if (!canRefresh(account.credentials)) await markAccountNeedsReauth(account.id) Type guard
function hasRefreshToken(c: { refreshToken?: string | null }): c is { refreshToken: string } {
return typeof c.refreshToken === 'string' && c.refreshToken.length > 0
} Try / catch
try {
await authProvider.refresh({ refreshToken })
} catch (e) {
if (e instanceof AppException && e.code === ResponseCode.ChannelAuthRefreshTokenMissing) {
await markAccountNeedsReauth(accountId)
return
}
throw e
} Prevention
- Persist refresh_token from TikTok's token response at connect time — never store accessToken only.
- Add a startup/data check flagging credential records missing refreshToken.
- Include offline access scope so TikTok issues refresh tokens.
- Make re-auth a first-class account state instead of throwing in batch jobs.
When it happens
Trigger: Calling tiktokAuthProvider.refresh({ refreshToken: undefined }) — typically for an account whose stored credentials only contain an accessToken, or where refresh_token was never persisted during connect.
Common situations: Cron/refresh job iterating accounts where TikTok connect flow didn't save refreshToken; manual DB edit wiped the field; account connected via a flow that returns long-lived tokens without refresh tokens; field renamed during a schema migration.
Related errors
- ChannelAuthRefreshTokenMissing
- ChannelAuthRefreshTokenMissing
- No response from Gemini
- ChannelAccessTokenFailed
- ChannelRefreshTokenFailed
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/90f9c749beae5819.
Report an issue: GitHub.