DIYgod/RSSHub · error · Error

Unknown post type: ${type}

Error message

Unknown post type: ${type}

What it means

A default-branch throw in renderPost's switch, fired when an otobanana post's type_label is neither 'cast' nor 'message'. Each known type has a dedicated renderer; anything else means the API returned a post shape the renderer was never taught to handle.

Source

Thrown at lib/routes/otobanana/utils.tsx:70

    comments: live.comment_count,
});

const renderPost = ({ id, type_label: type, cast, /** livestream  */ message /** , event */ }) => {
    switch (type) {
        case 'cast':
            return renderCast(cast);
        case 'message':
            return {
                title: message.text.split('\n', 1)[0],
                description: message.text.replaceAll('\n', '<br>'),
                pubDate: parseDate(message.created_at),
                link: `https://otobanana.com/${type}/${id}`,
                author: `${message.user.name} (@${message.user.username})`,
                upvotes: message.like_count,
                comments: message.comment_count,
            };
        default:
            throw new Error(`Unknown post type: ${type}`);
    }
};

export { apiBase, baseUrl, getUserInfo, renderCast, renderLive, renderPost };

View on GitHub (pinned to bed535e087)

Solutions

  1. Inspect the failing post object (log the full payload) to learn the new type_label value.
  2. Add a renderer case for the new type (reuse renderLive from utils.tsx for 'live', etc.).
  3. If some posts should be skipped rather than fatal, return a filtered-out sentinel and drop it instead of throwing.
  4. Keep the switch exhaustive by deriving the union of supported types from a shared constant.

Example fix

// before
default:
    throw new Error(`Unknown post type: ${type}`);

// after — skip unsupported types instead of failing the whole feed
const KNOWN_TYPES = new Set(['cast', 'message', 'live']);
// in caller:
const items = posts.map(renderPost).filter((item) => item !== null);
// in renderPost default:
default:
    return null; // caller filters nulls
Defensive patterns

Strategy: type-guard

Validate before calling

const SUPPORTED_POST_TYPES = new Set(['cast', 'message']);
function shouldRender(type: string): boolean {
    return SUPPORTED_POST_TYPES.has(type);
}
const renderable = posts.filter((p) => shouldRender(p.type_label));

Type guard

type SupportedPostType = 'cast' | 'message';
const isSupportedPostType = (t: string): t is SupportedPostType => t === 'cast' || t === 'message';

Try / catch

// Make renderPost total: unknown types yield null and the caller drops them.
function tryRenderPost(post: any) {
    try {
        return renderPost(post);
    } catch (e) {
        if (e instanceof Error && /Unknown post type/.test(e.message)) return null;
        throw e;
    }
}
const items = posts.map(tryRenderPost).filter((x): x is NonNullable<typeof x> => x !== null);

Prevention

When it happens

Trigger: The otobanana API returns a post whose type_label is a new/unexpected value (e.g. 'live', 'event', 'poll'). renderPost destructures type_label from the post and switches on it; the default branch throws, surfacing the unhandled type verbatim.

Common situations: Otobanana shipped a new post type (livestream, event) after the route was written; a post object has type_label undefined because a field was renamed upstream, so the switch falls through to default.

Related errors


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