yikart/AiToEarn · error · InstagramPlatformException
15070
15070
Error message
{{platform}} platform API request failed What it means
InstagramService's axios interceptor converts every failed Graph API request into an InstagramPlatformException with ResponseCode.ChannelPlatformApiFailed (15070). Network-level Axios failures (no response) and non-2xx responses from graph.facebook.com (or the configured graphApiBaseUrl) are both wrapped, with the Instagram error body parsed for platform code/message. The exception records endpoint, method, HTTP status, category, retryability, and the raw platform payload.
Source
Thrown at project/aitoearn-backend/apps/aitoearn-server/src/core/channels/platforms/instagram/instagram.service.ts:38
import { InstagramConfig } from './instagram.config'
import { InstagramPlatformException } from './instagram.exception'
import { InstagramOAuthGrantType } from './instagram.interface'
import { InstagramMediaContainerStatusResponseSchema, InstagramMediaType } from './instagram.schema'
@Injectable()
export class InstagramService {
private readonly http: AxiosInstance
constructor(private readonly cfg: InstagramConfig) {
this.http = this.createHttpClient()
}
private createHttpClient(): AxiosInstance {
const http = axios.create()
http.interceptors.response.use(
response => response,
(error: AxiosError<InstagramErrorBody>) => {
throw InstagramPlatformException.fromAxiosError(error)
},
)
return http
}
private get graphApiBaseUrl(): string {
return `https://graph.instagram.com/${this.cfg.graphApiVersion}`
}
generateAuthUrl(scopes: string[], state: string): string {
const params = new URLSearchParams({
client_id: this.cfg.clientId,
redirect_uri: this.cfg.redirectUri,
scope: scopes.join(','),
state,
response_type: 'code',
})
View on GitHub (pinned to d3aa8bea5b)
Solutions
- Inspect the thrown InstagramPlatformException's cause (platformCode, platformMessage, httpStatus) to get Meta's specific error subcode and message.
- If httpStatus is 401/190 (invalid token), re-authenticate the channel or refresh the long-lived token before retrying.
- If the error indicates missing permission (code 200/102), re-run OAuth with instagram_basic, instagram_content_publish, pages_show_list scopes and re-link the account.
- If retryable (429/5xx/network), back off and retry; Meta rate limits require waiting per X-Business-Use-Case-Usage headers.
- Confirm the target account is an Instagram Business/Creator account linked to a Facebook Page, and that the configured Graph API version is still supported.
Example fix
// before: expired token causes 190 error wrapped as 15070
const res = await this.http.get(`${this.graphApiBaseUrl}/${igUserId}?fields=followers_count`, { params: { access_token: token } })
// after: detect token failure and refresh
try {
const res = await this.http.get(`${this.graphApiBaseUrl}/${igUserId}`, { params: { fields: 'followers_count', access_token: token } })
} catch (e) {
if (e instanceof InstagramPlatformException && e.cause?.platformCode === 190) {
token = await this.refreshLongLivedToken(channel)
// retry request with new token
} else throw e
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: token present, not expired, and account is a linked IG business account
if (!accessToken || tokenExpiresAt <= new Date()) await refreshLongLivedToken(channel)
if (!igUserId) throw new Error('Channel has no linked instagram_business_account; re-link via OAuth') Type guard
function isInstagramPlatformException(e: unknown): e is InstagramPlatformException {
return e instanceof InstagramPlatformException
} Try / catch
try {
const result = await instagramService.publish(accessToken, igUserId, payload)
} catch (e) {
if (e instanceof InstagramPlatformException) {
if (e.cause?.platformCode === 190 || e.cause?.httpStatus === 401) {
// refresh token and retry once
} else if (e.retryable) {
// backoff retry (429 / 5xx / network)
} else {
// surface cause.platformMessage to the channel owner
}
} else throw e
} Prevention
- Keep Meta long-lived tokens fresh and re-authenticate channels before token expiry (~60 days).
- Ensure the Instagram account is Business/Creator type and linked to a Facebook Page before connecting the channel.
- Request all needed scopes (instagram_basic, instagram_content_publish, pages_show_list) during OAuth to avoid 403 permission errors.
- Track Meta BUC usage headers and throttle bulk publishing to avoid 429 rate limits.
- Pin and periodically review the Graph API version your service targets; deprecations cause sudden failures.
When it happens
Trigger: Any request through this.http — publishing media, fetching Instagram business account info, querying insights, exchanging tokens — that returns a non-2xx Graph API response (invalid OAuth token, missing instagram_business_account, permission denied, rate limit, invalid media params) or fails at the network level (timeout, DNS, connection refused).
Common situations: Facebook/Instagram access token expired or app-scoped token lacking instagram_basic/instagram_content_publish permissions; account not converted to an Instagram Business/Creator account and not linked to a Facebook Page; Graph API version deprecation after version changes; Meta rate limiting (code 4, 613) during bulk posting; egress blocked to graph.facebook.com.
Related errors
AI-assisted analysis of yikart/AiToEarn@d3aa8bea5b (2026-08-31).
Data as JSON: /api/errors/cf15d0e313356144.
Report an issue: GitHub.