jackwener/OpenCLI · error

Sina blog search failed: HTTP ${resp.status}

Error message

Sina blog search failed: HTTP ${resp.status}

What it means

searchSinaBlog in clis/sinablog/search.js queries Sina's public search API (search.sina.com.cn/api/search) and throws a plain Error when resp.ok is false, embedding the HTTP status. There is no retry or key handling — any non-2xx (403 anti-bot, 429 throttle, 5xx outage) surfaces as this error.

Source

Thrown at clis/sinablog/search.js:23

function stripHtml(value) {
    return value.replace(/<[^>]+>/g, '');
}
async function searchSinaBlog(keyword, limit) {
    const url = new URL('https://search.sina.com.cn/api/search');
    url.searchParams.set('q', keyword);
    url.searchParams.set('tp', 'mix');
    url.searchParams.set('sort', '0');
    url.searchParams.set('page', '1');
    url.searchParams.set('size', String(Math.max(limit, 10)));
    url.searchParams.set('from', 'search_result');
    const resp = await fetch(url, {
        headers: {
            'User-Agent': 'Mozilla/5.0',
            Accept: 'application/json',
        },
    });
    if (!resp.ok)
        throw new Error(`Sina blog search failed: HTTP ${resp.status}`);
    const data = await resp.json();
    const list = Array.isArray(data?.data?.list) ? data.data.list : [];
    return list
        .filter((item) => normalize(item?.url).includes('blog.sina.com.cn/s/blog_'))
        .slice(0, limit)
        .map((item, index) => ({
        rank: index + 1,
        title: normalize(stripHtml(item?.title || '')),
        author: normalize(item?.media_show || item?.author),
        date: normalize(item?.time || item?.dataTime),
        description: normalize(item?.intro || item?.searchSummary).slice(0, 150),
        url: normalize(item?.url),
    }));
}
cli({
    site: 'sinablog',
    name: 'search',
    access: 'read',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry after a delay — 429/5xx are often transient.
  2. Use a realistic browser User-Agent and route through a residential/network path not blocked by Sina.
  3. Check whether the search API endpoint/params changed and update the URL or params.
  4. Reduce request frequency and add backoff between searches.
  5. Fall back to another Sina search surface or a cached index if the API is down.

Example fix

// before
if (!resp.ok) throw new Error(`Sina blog search failed: HTTP ${resp.status}`);
// after: retry once with backoff on 429/5xx
let resp = await fetch(url, { headers });
if (resp.status === 429 || resp.status >= 500) {
  await new Promise(r => setTimeout(r, 2000));
  resp = await fetch(url, { headers });
}
if (!resp.ok) throw new Error(`Sina blog search failed: HTTP ${resp.status}`);
Defensive patterns

Strategy: retry

Validate before calling

const keywordOk = typeof keyword === 'string' && keyword.trim().length > 0;
const limitOk = Number.isInteger(limit) && limit >= 1 && limit <= 50;
if (!keywordOk || !limitOk) throw new Error('Invalid search keyword or limit');

Try / catch

try {
  const results = await searchSinaBlog(keyword, limit);
} catch (err) {
  const m = /HTTP (\d{3})/.exec(err.message);
  if (m && (+m[1] === 429 || +m[1] >= 500)) {
    await new Promise(r => setTimeout(r, 2000));
    return searchSinaBlog(keyword, limit); // one retry
  }
  if (m && +m[1] === 403) console.error('Blocked by Sina; use a browser-like UA or different network');
  throw err;
}

Prevention

When it happens

Trigger: fetch to https://search.sina.com.cn/api/search?q=... returns a non-ok status: Sina's WAF blocking the default 'Mozilla/5.0' UA with 403, rate limiting with 429, or backend 5xx during outages.

Common situations: Running from datacenter IPs Sina blocks; heavy scripted searches tripping rate limits; Sina search API deprecations/changes returning error statuses; regional network restrictions.

Related errors


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