{"record":{"id":"60084dfa90b1966f","repo":"gitroomhq/postiz-app","slug":"handleerror-value-60084d","errorCode":null,"errorMessage":"${handleError.value}","messagePattern":"\\$\\{handleError\\.value\\}","errorType":"exception","errorClass":"RefreshToken","httpStatus":null,"severity":"error","filePath":"libraries/nestjs-libraries/src/integrations/social/tiktok.business.provider.ts","lineNumber":463,"sourceCode":"    } catch (err) {\n      if (err instanceof RefreshToken || err instanceof Disconnect) {\n        throw err;\n      }\n\n      // Transient API error while checking the status: the post may already\n      // be live, so keep polling instead of failing it - if the API stays\n      // broken the caller exhausts its checks and warns the user properly.\n      return { status: 'pending', pendingData };\n    }\n\n    // Errors arrive as HTTP 200 with a non-zero code, invisible to this.fetch:\n    // a token error must surface as RefreshToken, anything else is treated as\n    // transient and keeps polling (same rationale as the catch above).\n    if (post?.code !== 0) {\n      const asString = JSON.stringify(post);\n      const handleError = this.handleErrors(asString);\n      if (handleError?.type === 'refresh-token') {\n        throw new RefreshToken('tiktok-business', asString, '{}', handleError.value);\n      }\n      if (handleError?.type === 'disconnect') {\n        throw new Disconnect('tiktok-business', asString, '{}', handleError.value);\n      }\n      return { status: 'pending', pendingData };\n    }\n\n    const { status, post_ids, reason } = post?.data || {};\n\n    if (status === 'SEND_TO_USER_INBOX') {\n      return {\n        status: 'completed',\n        releaseURL: 'https://www.tiktok.com/messages?lang=en',\n        postId: 'missing',\n      };\n    }\n\n    if (status === 'PUBLISH_COMPLETE') {","sourceCodeStart":445,"sourceCodeEnd":481,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/integrations/social/tiktok.business.provider.ts#L445-L481","documentation":"While polling a direct-post's status, a non-zero code body is classified by handleErrors; if the classified type is 'refresh-token' a RefreshToken error is thrown so the framework refreshes the access token and retries. The message comes from handleError.value.","triggerScenarios":"The TikTok status endpoint returns an access_token expired/invalid error code, which handleErrors maps to type 'refresh-token'.","commonSituations":"Channel idle long enough for the access token to expire; token refreshed elsewhere causing the old one to be invalidated.","solutions":["Let the framework handle it - RefreshToken triggers automatic refresh+retry","If it persists, the refresh token itself is dead: reconnect the channel","Check that refresh logic actually runs (refreshToken endpoint configured)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":"const isRefreshTokenError = (e: unknown): e is RefreshToken => e instanceof Error && /token/i.test((e as any).type || '') || e instanceof RefreshToken;","tryCatchPattern":"try { await checkPost(post); } catch (e) { if (e instanceof RefreshToken) { await refreshChannelToken(e.identifier); return checkPost(post); } throw e; }","preventionTips":["Run RefreshToken-aware retry wrappers around all TikTok status checks","Refresh channel tokens proactively on a cron","Log token error codes to spot refresh-loop patterns"],"tags":["tiktok","token-expired","refresh-token","post-status"],"backgroundTag":"access-token-expired","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}