gitroomhq/postiz-app · error · BadBody

${handleError?.value || information?.message || 'Could not l

Error message

${handleError?.value || information?.message || 'Could not load the TikTok business account'}

What it means

fetchUserInformation calls TikTok's Business API user endpoint during OAuth. TikTok returns errors as HTTP 200 with a non-zero code, so the provider checks information.code !== 0 and throws BadBody with TikTok's message instead of silently creating a channel with undefined name/picture.

Source

Thrown at libraries/nestjs-libraries/src/integrations/social/tiktok.business.provider.ts:280

        )}&fields=${encodeURIComponent(
          JSON.stringify(['username', 'display_name', 'profile_image'])
        )}`,
        {
          method: 'GET',
          headers: {
            'Access-Token': accessToken,
          },
        }
      )
    ).json();

    // A non-zero code arrives as HTTP 200: without this check the auth flow
    // would "succeed" with an undefined name/picture/profile and create a
    // broken channel.
    if (information?.code !== 0) {
      const asString = JSON.stringify(information);
      const handleError = this.handleErrors(asString);
      throw new BadBody(
        'tiktok-business',
        asString,
        Buffer.from('{}'),
        handleError?.value ||
          information?.message ||
          'Could not load the TikTok business account'
      );
    }

    return {
      display_name: information.data?.display_name,
      profile_image: information.data?.profile_image,
      username: information.data?.username,
    };
  }

  async refreshToken(refreshToken: string): Promise<AuthTokenDetails> {
    const response = await (

View on GitHub (pinned to 0f1647f749)

Solutions

  1. Check the logged JSON body - code+message name the exact API error
  2. Verify the TikTok app has user.info.basic scope and the account is a Business account
  3. Re-run the OAuth flow to get a fresh token
  4. Confirm app_id/secret pair matches the one used for auth_code exchange
Defensive patterns

Strategy: try-catch

Validate before calling

// after token exchange, sanity-check the user fetch before saving the channel
const info = await provider.fetchUserInformation(token);
if (info?.code !== 0 || !info?.data) throw new Error('TikTok user info incomplete; aborting channel creation');

Type guard

const isTikTokOk = (r: any): r is { code: 0; data: Record<string, any> } => r?.code === 0 && !!r?.data;

Try / catch

try { await connectTikTokBusiness(code); } catch (e) { if (/TikTok business account/.test(e.message)) showReconnectFlow(); else throw e; }

Prevention

When it happens

Trigger: The /user/info/ call returns code != 0: invalid/expired access_token, missing scopes (user.info.basic), or sandbox app not approved for the queried advertiser.

Common situations: App missing the user info scope, token exchanged against the wrong app_id/secret pair, or the TikTok account has no business/advertiser profile attached.

Related errors


AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27). Data as JSON: /api/errors/9c6b21995a0f76cc. Report an issue: GitHub.