DIYgod/RSSHub · error · Error

Unhandle asset type

Error message

Unhandle asset type: ${a.asset_type}

What it means

Thrown by the ArtStation user route while rendering each project's assets. After fetching a project's JSON, the handler iterates data.assets and only knows how to render asset_type values of 'video', 'image', 'video_clip', and 'cover'. Any other asset_type (the comment lists model3d, marmoset, pano) is treated as unrenderable and aborts the whole feed rather than silently dropping content.

Solutions

  1. If you control the route, extend the allow-list to include the new asset_type (e.g. add 'model3d', 'marmoset', 'pano') and provide rendering for it, or downgrade the throw to a continue/skip so one unhandled asset does not kill the feed.
  2. If you are only consuming the feed, filter the offending user or wait for a route update; file an issue quoting the asset_type value from the error message.

Example fix

// before
for (const a of data.assets) {
    if (a.asset_type !== 'video' && a.asset_type !== 'image' && a.asset_type !== 'video_clip' && a.asset_type !== 'cover') {
        throw new Error(`Unhandle asset type: ${a.asset_type}`);
    }
}

// after: skip unknown asset types instead of aborting the feed
const KNOWN = new Set(['video', 'image', 'video_clip', 'cover', 'model3d', 'marmoset', 'pano']);
for (const a of data.assets) {
    if (!KNOWN.has(a.asset_type)) {
        continue;
    }
}
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN_ASSET_TYPES = new Set(['video', 'image', 'video_clip', 'cover']);
const unknown = (data.assets ?? []).filter((a) => !KNOWN_ASSET_TYPES.has(a.asset_type));
if (unknown.length) {
    // log/branch before the throw site
    logger.warn(`Skipping ${unknown.length} unhandled asset(s): ${unknown.map((a) => a.asset_type).join(', ')}`);
}

Type guard

const KNOWN_ASSET_TYPES = new Set(['video', 'image', 'video_clip', 'cover']);
function isKnownAsset(a: { asset_type: string }): boolean {
    return KNOWN_ASSET_TYPES.has(a.asset_type);
}

Prevention

When it happens

Trigger: A user publishes an ArtStation project containing a 3D model (model3d), a Marmoset Viewer scene (marmoset), or a 360 panorama (pano), and that project is fetched in the detail loop (assetsCount > 1 or no image icon). The loop hits the unhandled asset_type branch and throws.

Common situations: Artists uploading 3D/pano content; ArtStation adding a new asset_type to their API that the route was never updated to handle; rendering the feed of a user whose portfolio mixes 2D and 3D work.

Related errors


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

Appendix: source

Thrown at lib/routes/artstation/user.ts:106

    const items = await Promise.all(
        list.map((item) =>
            cache.tryGet(item.link, async () => {
                if (item.assetsCount > 1 || !item.icons.image) {
                    const { data } = await got(`https://www.artstation.com/projects/${item.hashId}.json`, {
                        headers: {
                            ...headers,
                            cookie: `PRIVATE-CSRF-TOKEN=${csrfToken}`,
                        },
                    });

                    item.description = renderDescription({
                        description: data.description,
                        assets: data.assets,
                    });

                    for (const a of data.assets) {
                        if (a.asset_type !== 'video' && a.asset_type !== 'image' && a.asset_type !== 'video_clip' && a.asset_type !== 'cover') {
                            throw new Error(`Unhandle asset type: ${a.asset_type}`); // model3d, marmoset, pano
                        }
                    }
                }

                return item;
            })
        )
    );

    return {
        title: `${userData.full_name} - ArtStation`,
        description: userData.headline,
        link: userData.permalink,
        logo: userData.large_avatar_url,
        icon: userData.large_avatar_url,
        image: userData.default_cover_url,
        item: items,
    };

View on GitHub (pinned to bed535e087)