DIYgod/RSSHub · error · Error

Cannot get the redirect link

Error message

Cannot get the redirect link

What it means

Thrown by t66y/post.ts:67 via `throw new Error(...)` (NOT an InvalidParameterError) when $('a:last-child').attr('href') is falsy on the first response. t66y serves an interstitial redirect page at /read.php?tid=... containing an <a> link the route follows to reach the real thread; if that anchor is absent, the redirect cannot be resolved. The route is flagged antiCrawler: true, so the most common real cause is being blocked or served a non-redirect page rather than a genuine markup change.

Source

Thrown at lib/routes/t66y/post.ts:67

    },
    name: '帖子跟踪',
    maintainers: ['cnzgray'],
    handler,
    description: `::: tip
帖子 id 查找办法:

打开想跟踪的帖子,比如:\`https://t66y.com/htm_data/20/1811/3286088.html\` 其中 \`3286088\` 就是帖子 id。
:::`,
};

async function handler(ctx) {
    const tid = ctx.req.param('tid') as string;
    const { data: response } = await got(`${baseUrl}/read.php?tid=${tid}`);
    // 跟踪重定向
    let $ = load(response);
    const redirect = $('a:last-child').attr('href');
    if (!redirect) {
        throw new Error('Cannot get the redirect link');
    }

    const { data: redirectedResponse, url: link } = await got(new URL(redirect, baseUrl).href);
    $ = load(redirectedResponse);

    const firstPage = parseItems(tid, $);

    const pageSize = $('.w70 input').eq(0).attr('value')?.split('/', 2)[1];
    let pageUrls: string[] = [];
    if (pageSize) {
        const length = Number.parseInt(pageSize);
        pageUrls = Array.from({ length }, (_, i) => `${baseUrl}/read.php?tid=${tid}&page=${i + 1}`).slice(1);
    }

    // 请求帖子
    const nextPages = pageSize
        ? await Promise.all(
              pageUrls.map((url) =>

View on GitHub (pinned to bed535e087)

Solutions

  1. Retry after a short delay — transient anti-bot blocks often clear.
  2. Open https://t66y.com/read.php?tid=<tid> in a browser to see the actual page returned (block page, error, or changed markup).
  3. If the markup changed, update the selector (currently a:last-child) in post.ts.
  4. Confirm the tid corresponds to a live thread.

Example fix

// before
const redirect = $('a:last-child').attr('href');
if (!redirect) {
    throw new Error('Cannot get the redirect link');
}
// after (fail with richer context + try alternate selectors)
const redirect = $('a:last-child').attr('href') ?? $('a.continue').attr('href');
if (!redirect) {
    throw new Error(`Cannot get the redirect link for tid=${tid} (possible anti-bot block or markup change)`);
}
Defensive patterns

Strategy: retry

Validate before calling

// Pre-validate the tid shape; the real cause is usually server-side.
function isPlausibleTid(tid: string): boolean {
  return typeof tid === 'string' && /^\d+$/.test(tid) && tid.length > 0;
}

Type guard

function isTid(tid: string): tid is string {
  return typeof tid === 'string' && /^\d+$/.test(tid);
}

Try / catch

// t66y blocks are often transient — retry with backoff.
async function fetchThread(tid: string, attempts = 3) {
  for (let i = 0; i < attempts; i++) {
    try {
      return await fetchFeed(`/t66y/post/${tid}`);
    } catch (e) {
      const last = i === attempts - 1;
      if (last || !(e instanceof Error) || !/redirect link/i.test(e.message)) throw e;
      await wait(Math.pow(2, i) * 1000); // host-provided wait primitive
    }
  }
}

Prevention

When it happens

Trigger: t66y returns a Cloudflare/WAF block page instead of the redirect interstitial; the tid is invalid/deleted and the page shows an error with no link; the site changed its redirect markup so a:last-child no longer matches; t66y is down or geo-blocked.

Common situations: Anti-bot block (rate limiting from the RSSHub IP); expired/removed thread; geographic restriction; markup change after a site update.

Related errors


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/835c086334e77359. Report an issue: GitHub.