{"record":{"id":"17e23e7f738ad9d3","repo":"yikart/AiToEarn","slug":"channelauthrefreshtokenmissing-17e23e","errorCode":"ChannelAuthRefreshTokenMissing","errorMessage":"ChannelAuthRefreshTokenMissing","messagePattern":"ChannelAuthRefreshTokenMissing","errorType":"error_code","errorClass":"AppException","httpStatus":null,"severity":"error","filePath":"project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/pinterest/pinterest-auth.provider.ts","lineNumber":47,"sourceCode":"\n    return { url, state: input.state, redirectUri: this.config.redirectUri }\n  }\n\n  async exchangeCode(input: AuthCallbackInput): Promise<CredentialResult> {\n    const callback = parseOAuthCallback(input)\n    const result = await this.pinterestService.exchangeCode(callback.code)\n\n    return {\n      accessToken: result.accessToken,\n      refreshToken: result.refreshToken,\n      expiresAt: result.expiresAt,\n      scope: result.scope,\n    }\n  }\n\n  async refresh(input: RefreshCredentialInput): Promise<CredentialResult> {\n    if (!input.refreshToken) {\n      throw new AppException(ResponseCode.ChannelAuthRefreshTokenMissing)\n    }\n\n    const result = await this.pinterestService.refreshAccessToken(input.refreshToken)\n\n    return {\n      accessToken: result.accessToken,\n      refreshToken: result.refreshToken,\n      expiresAt: result.expiresAt,\n      scope: result.scope,\n    }\n  }\n\n  async revoke(input: RevokeCredentialInput): Promise<void> {\n    try {\n      await this.pinterestService.revokeToken(input.accessToken)\n    }\n    catch (err) {\n      this.logger.warn(err, 'Failed to revoke Pinterest token')","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/yikart/AiToEarn/blob/d3aa8bea5b146a8675607cf0144d891aad3e9683/project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/pinterest/pinterest-auth.provider.ts#L29-L65","documentation":"ChannelAuthRefreshTokenMissing is thrown by the Pinterest auth provider's refresh() when input.refreshToken is missing. Pinterest token refresh requires the refresh token issued during OAuth; without it the provider cannot obtain a new accessToken and fails fast with this error.","triggerScenarios":"Calling refresh() on a Pinterest credential whose refreshToken field is null/undefined/empty string — credentials created without the refresh token persisted, or tokens cleared after user revocation.","commonSituations":"Pinterest connect flow not persisting refresh_token; manual DB seeding with access token only; Pinterest revoked the token so the stored refresh token was purged; account reconnected under a different app losing the token.","solutions":["Confirm the Pinterest OAuth flow persists the refresh_token returned by the token endpoint","Re-run the channel connection flow to issue a new refresh token","Audit stored Pinterest credentials for null refresh_token and re-auth those channels"],"exampleFix":"// before\nawait pinterestAuthProvider.refresh({ accessToken }) // throws ChannelAuthRefreshTokenMissing\n// after\nif (!credential.refreshToken) await reconnectChannel(credential.channelId)\nawait pinterestAuthProvider.refresh({ accessToken, refreshToken: credential.refreshToken })","handlingStrategy":"validation","validationCode":"if (!credential.refreshToken) {\n  throw new Error('Pinterest credential missing refresh token; reconnect the channel')\n}\nawait pinterestAuthProvider.refresh({ accessToken: credential.accessToken, refreshToken: credential.refreshToken })","typeGuard":"function hasRefreshToken(c: { refreshToken?: string | null }): c is { refreshToken: string } {\n  return typeof c.refreshToken === 'string' && c.refreshToken.length > 0\n}","tryCatchPattern":"try {\n  await pinterestAuthProvider.refresh(input)\n} catch (e) {\n  if (e instanceof AppException && e.code === ResponseCode.ChannelAuthRefreshTokenMissing) {\n    await markChannelNeedsReauth(channelId)\n  } else throw e\n}","preventionTips":["Persist Pinterest refresh_token at OAuth connect time","Guard refresh jobs to skip credentials lacking refresh tokens","Trigger channel reconnection when refresh token is absent","Audit credential storage for rows seeded without refresh tokens"],"tags":["pinterest","oauth","auth","missing-credential"],"backgroundTag":"missing-refresh-token","analyzedSha":"d3aa8bea5b146a8675607cf0144d891aad3e9683","analyzedAt":"2026-08-31T14:19:24.185Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}