DIYgod/RSSHub · error · Error

Unhandled thirdparty on ${link}: ${elem.attr('alias')}

Error message

Unhandled thirdparty on ${link}: ${elem.attr('alias')}

What it means

Thrown by the `card2Html` helper in the Yuque route while converting a Yuque `<card name="thirdparty">` (or `youku`) embed into HTML. The code only knows how to render the aliases `music163`, `bilibili`/`undefined`, and the `codepen` type; any other alias or type falls through to this throw. The message echoes the document `link` and the offending `alias` so a maintainer can identify which new third-party platform Yuque started supporting.

Source

Thrown at lib/routes/yuque/utils.ts:57

            break;
        case 'mention':
            html = `<a href='https://www.yuque.com/${value.login}'>${value.name}</a>`;
            break;
        case 'table':
            html = value.html;
            break;
        case 'thirdparty':
        case 'youku':
            // YES, youku name with bilibli iframe
            // https://www.yuque.com/api/docs/nn5lyk?book_id=297292&include_contributors=true
            if (elem.attr('alias') === 'music163') {
                html = `<iframe frameborder="no" border="0" marginwidth="0" marginheight="0" height=66 src="${value.src}"></iframe>`;
            } else if (elem.attr('alias') === 'bilibili' || elem.attr('alias') === undefined) {
                html = `<iframe src="${value.src}&high_quality=1&autoplay=0" width="650" height="477" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>`;
            } else if (value.type === 'codepen') {
                html = `<iframe height="265" style="width: 100%;" scrolling="no" title="codepen" src="${value.url}" frameborder="no" allowtransparency="true" allowfullscreen="true"></iframe>`;
            } else {
                throw new Error(`Unhandled thirdparty on ${link}: ${elem.attr('alias')}`);
            }
            break;
        case 'yuque':
            if (value.mode === 'card') {
                html = `<a href='${value.src}'>${value.detail.title}</a>`;
            } else if (value.mode === 'embed') {
                html = `<iframe src="${value.url}" width="100%" height="518"></iframe>`;
            } else {
                throw new Error(`Unhandled mode on ${link}: ${value.mode}`);
            }
            break;
        case 'video':
            // fake video src
            html = `<video src='${value.videoId}'></video>`;
            break;

        default:
            throw new Error(`Unhandled card on ${link}: ${name}`);

View on GitHub (pinned to bed535e087)

Solutions

  1. Read the `alias` value from the error message and add a new `else if` branch in the `thirdparty`/`youku` case that builds the correct iframe/HTML for that platform (typically using `value.src` or `value.url`).
  2. If the new embed is iframe-based, reuse the existing iframe template and swap in `value.src`/`value.url`.
  3. To stop one unknown embed from breaking the entire document feed, make the `else` branch skip the card (e.g. `html = ''` or leave `elem` in place) instead of throwing, and log the alias for follow-up.

Example fix

// before
} else {
    throw new Error(`Unhandled thirdparty on ${link}: ${elem.attr('alias')}`);
}
// after (add a branch for the new alias)
} else if (elem.attr('alias') === 'codesandbox') {
    html = `<iframe src="${value.src}" style="width:100%;height:500px;border:0;border-radius:4px;overflow:hidden;" allowfullscreen></iframe>`;
} else {
    html = '';
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before calling card2Html, snapshot which card names/aliases appear
const knownThirdpartyAliases = new Set(['music163', 'bilibili', undefined]);
const knownThirdpartyTypes = new Set(['codepen']);
function isHandledThirdparty(elem, value) {
    return knownThirdpartyAliases.has(elem.attr('alias')) || knownThirdpartyTypes.has(value.type);
}

Type guard

function isHandledThirdparty(elem: cheerio.Cheerio<unknown>, value: { type?: string }): boolean {
    const alias = elem.attr('alias');
    return alias === 'music163' || alias === 'bilibili' || alias === undefined || value.type === 'codepen';
}

Try / catch

// Wrap per-card conversion so one unhandled embed never kills the doc
try {
    card2Html(elem, link);
} catch (e) {
    logger.warn(`Skipping unhandled yuque thirdparty card on ${link}: ${(e as Error).message}`);
    elem.remove();
}

Prevention

When it happens

Trigger: A Yuque document embeds a third-party widget whose `alias` attribute is something other than `music163` / `bilibili` / `undefined`, and whose parsed `value.type` is not `codepen` — e.g. a newly added platform like CodeSandbox, Figma, or a video host Yuque integrated after this branch was written.

Common situations: Yuque ships a new third-party embed integration; the alias naming for an existing platform changes; the `value.type === 'codepen'` check stops matching because Yuque restructured the card payload. Any single affected document breaks the whole feed because the throw is not caught.

Related errors


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