yikart/AiToEarn · error · AppException
ChannelAuthRefreshTokenMissing
ChannelAuthRefreshTokenMissing
Error message
ChannelAuthRefreshTokenMissing
What it means
Twitter credential refresh requires a stored refresh token; refresh() throws ChannelAuthRefreshTokenMissing when input.refreshToken is missing. Twitter OAuth2 (PKCE) refresh tokens can also be rotated/invalidated, so accounts may legitimately lack a usable one.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/twitter/twitter-auth.provider.ts:65
}
}
async exchangeCode(input: AuthCallbackInput): Promise<CredentialResult> {
const callback = parseOAuthCallback(input)
const codeVerifier = parseAuthCodeVerifier(input)
const result = await this.twitterService.exchangeCode(callback.code, codeVerifier)
return {
accessToken: result.accessToken,
refreshToken: result.refreshToken,
expiresAt: result.expiresAt,
scope: result.scope,
}
}
async refresh(input: RefreshCredentialInput): Promise<CredentialResult> {
if (!input.refreshToken) {
throw new AppException(ResponseCode.ChannelAuthRefreshTokenMissing)
}
const result = await this.twitterService.refreshAccessToken(input.refreshToken)
return {
accessToken: result.accessToken,
refreshToken: result.refreshToken,
expiresAt: result.expiresAt,
scope: result.scope,
}
}
async revoke(input: RevokeCredentialInput): Promise<void> {
await this.twitterService.revokeToken(input.accessToken)
}
async getProfile(input: CredentialContext): Promise<PlatformAccountProfile> {
const userInfo = await this.twitterService.getUserInfo(input.accessToken)View on GitHub (pinned to d3aa8bea5b)
Solutions
- Check the stored credentials for the Twitter account — if refreshToken is empty, re-run the Twitter OAuth connect flow (with offline_access scope) to get and persist one.
- Fix the token-exchange/refresh path so every new refresh_token returned by Twitter (rotations included) is written back to storage.
- Ensure the initial authorize request includes the offline_access scope; otherwise no refresh token is issued.
- Have the refresh job mark such accounts as needing re-authorization instead of throwing per account.
Example fix
// before
await authProvider.refresh({ refreshToken: account.credentials.refreshToken })
// after
if (!account.credentials.refreshToken) {
await markAccountNeedsReauth(account.id)
} else {
const result = await authProvider.refresh({ refreshToken: account.credentials.refreshToken })
await saveCredentials(account.id, result) // persist rotated refresh token
} Defensive patterns
Strategy: validation
Validate before calling
function canRefreshTwitter(creds: TwitterCredentials): boolean {
return typeof creds.refreshToken === 'string' && creds.refreshToken.length > 0
}
if (!canRefreshTwitter(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
- Always request offline_access scope so Twitter issues a refresh token.
- Persist rotated refresh tokens on every refresh — Twitter rotates them.
- Flag accounts missing refreshToken for re-authorization instead of throwing in batch jobs.
- Monitor refresh_token_invalid responses; they usually mean rotation was mishandled.
When it happens
Trigger: Calling twitterAuthProvider.refresh({ refreshToken: undefined }) — account connected without persisting refresh_token, credential record cleared, or refresh token consumed during a previous rotation and not re-saved.
Common situations: Refresh job processing an account whose Twitter connect flow never stored refresh_token; refresh-token rotation in Twitter OAuth2 invalidated the stored value and the new one wasn't saved; DB cleanup/migration dropped the field; offline_access scope missing at connect time so Twitter never issued a refresh token.
Related errors
- ChannelAuthRefreshTokenMissing
- ChannelAuthRefreshTokenMissing
- 无效的账号或刷新令牌丢失
- ChannelAccessTokenFailed
- ChannelRefreshTokenFailed
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/4578f4a3d04072da.
Report an issue: GitHub.