{"record":{"id":"94ad28ae7bd64703","repo":"gitroomhq/postiz-app","slug":"handleerror-value-publish-message-tikto","errorCode":null,"errorMessage":"${handleError?.value || publish?.message || 'TikTok refused the post'}","messagePattern":"\\$\\{handleError\\?\\.value \\|\\| publish\\?\\.message \\|\\| 'TikTok refused the post'\\}","errorType":"exception","errorClass":"BadBody","httpStatus":null,"severity":"error","filePath":"libraries/nestjs-libraries/src/integrations/social/tiktok.business.provider.ts","lineNumber":712,"sourceCode":"      const asString = JSON.stringify(publish);\n      const handleError = this.handleErrors(asString);\n      if (handleError?.type === 'refresh-token') {\n        throw new RefreshToken(\n          'tiktok-business',\n          asString,\n          JSON.stringify(body),\n          handleError.value\n        );\n      }\n      if (handleError?.type === 'disconnect') {\n        throw new Disconnect(\n          'tiktok-business',\n          asString,\n          JSON.stringify(body),\n          handleError.value\n        );\n      }\n      throw new BadBody(\n        'tiktok-business-error-upload',\n        asString,\n        Buffer.from(JSON.stringify(body)),\n        handleError?.value || publish?.message || 'TikTok refused the post'\n      );\n    }\n\n    // The publish is now irreversible on TikTok's side: return `pending` so the\n    // workflow polls checkPostStatus instead of blocking (and possibly timing\n    // out and re-posting) inside this activity.\n    return [\n      {\n        id: firstPost.id,\n        releaseURL: '',\n        postId: '',\n        status: 'pending',\n        pendingData: { publishId: publish.data.share_id },\n      },","sourceCodeStart":694,"sourceCodeEnd":730,"githubUrl":"https://github.com/gitroomhq/postiz-app/blob/0f1647f7491a217d43eb5ae7a480484bdf0aff3e/libraries/nestjs-libraries/src/integrations/social/tiktok.business.provider.ts#L694-L730","documentation":"postPending's final fallback: the publish envelope has code != 0 / no share_id and the error was not classified as refresh-token or disconnect, so a BadBody 'TikTok refused the post' is thrown with TikTok's message.","triggerScenarios":"Business API rejects the direct post request itself: invalid video_id (expired upload), unsupported field combination, rate limit, or param validation error.","commonSituations":"Video uploaded but publish delayed past the video's validity window, wrong privacy option for the app's scopes, or hitting the daily post quota.","solutions":["Read the logged asString body - code/message identify the refusal reason","Publish promptly after video upload so the video_id is still valid","Verify the app has the scopes required for the chosen privacy level","Check TikTok rate/quota limits"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// publish promptly after upload so video_id stays valid\nif (Date.now() - upload.finishedAt > 60 * 60 * 1000) await reuploadVideo();","typeGuard":"const isRefusedEnvelope = (p: any) => p?.code !== 0 || !p?.data?.share_id;","tryCatchPattern":"try { await provider.postPending(...); } catch (e) { if (e instanceof BadBody && /refused the post/.test(e.message)) surfaceApiReason(e.error); throw e; }","preventionTips":["Publish within minutes of video upload","Verify app scopes cover the chosen privacy level","Parse and display TikTok's code/message from the logged body"],"tags":["tiktok","publish-rejected","business-api","validation"],"backgroundTag":"social-post-rejected","analyzedSha":"0f1647f7491a217d43eb5ae7a480484bdf0aff3e","analyzedAt":"2026-08-27T12:09:55.020Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}