jackwener/OpenCLI · error · CommandExecutionError

Malformed response from Douyin API (${method} ${url})

Error message

Malformed response from Douyin API (${method} ${url})

What it means

browserFetch validates that the JSON returned by a Douyin API endpoint is a plain object. When the parsed body is an array or a non-object (string/number/null), it means the endpoint no longer returns the expected envelope, so the library throws this CommandExecutionError instead of letting downstream parsing fail confusingly.

Source

Thrown at clis/douyin/_shared/browser-fetch.js:60

        clearTimeout(timer);
      }
    })()
  `;
    let result;
    try {
        result = unwrapEvaluateResult(await page.evaluate(js));
    }
    catch (error) {
        throw new CommandExecutionError(`Douyin API request failed (${method} ${url}): ${error instanceof Error ? error.message : String(error)}`);
    }
    if (result == null) {
        throw new CommandExecutionError(
            `Empty response from Douyin API (${method} ${url})`,
            'The endpoint may have been retired or may now require signed parameters.',
        );
    }
    if (Array.isArray(result) || typeof result !== 'object') {
        throw new CommandExecutionError(`Malformed response from Douyin API (${method} ${url})`);
    }
    if (result && typeof result === 'object' && 'status_code' in result) {
        const code = result.status_code;
        if (code !== 0) {
            const msg = result.status_msg ?? result.message ?? 'unknown error';
            if (isAuthLikeError(code, msg)) {
                throw new AuthRequiredError('creator.douyin.com', `Douyin API auth/permission error ${code} at ${method} ${url}: ${msg}`);
            }
            throw new CommandExecutionError(`Douyin API error ${code} at ${method} ${url}: ${msg}`);
        }
    }
    return result;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-authenticate the browser session on creator.douyin.com (log in again / refresh cookies) and retry.
  2. Verify the endpoint URL is current and still returns the expected object envelope (curl it and inspect the body).
  3. Log the raw response body before parsing to see what is actually being returned (HTML vs JSON).
  4. Update the library or adjust the endpoint if Douyin changed the API response contract.

Example fix

// before: assuming any JSON is fine
const data = await browserFetch(page, url);
console.log(data.items);
// after: catch and inspect
try {
  const data = await browserFetch(page, url);
  console.log(data.items);
} catch (e) {
  if (String(e.message).includes('Malformed response')) {
    console.error('Session likely expired or endpoint retired; re-login to creator.douyin.com');
  }
  throw e;
}
Defensive patterns

Strategy: type-guard

Validate before calling

function isPlainObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); }
if (!isPlainObject(json)) throw new Error('endpoint returned non-object body — re-authenticate or check URL');

Type guard

function isDouyinEnvelope(v): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

try {
  const data = await browserFetch(page, url);
} catch (e) {
  if (String(e.message).startsWith('Malformed response from Douyin API')) {
    await refreshSession(page); // dump body + re-login
  }
  throw e;
}

Prevention

When it happens

Trigger: The requested endpoint returns HTML (redirect/login page), an array, a string, or any non-object JSON. Typical with retired endpoints, anti-bot interstitials, or when cookies are missing and the server responds with a non-JSON-shaped body.

Common situations: Douyin changed an API response shape after a site update; the browser session was redirected to a login/captcha page whose JSON parse yields a non-object; the caller pointed at the wrong URL; expired cookies cause a soft-redirect response.

Understand the failure class

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/37ce8e1fbda53ef1. Report an issue: GitHub.