DIYgod/RSSHub · error · ConfigNotFoundError

GitHub notification RSS is disabled due to the lack of <a hr

Error message

GitHub notification RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>

What it means

Thrown as a ConfigNotFoundError by the GitHub Notifications route when config.github.access_token is not set. Unlike the other GitHub routes which use GraphQL, this route uses the REST API (api.github.com/notifications via ofetch.raw) with Bearer token authentication. The notifications endpoint is inherently user-scoped and requires a token with the 'notifications' scope.

Source

Thrown at lib/routes/github/notifications.ts:34

                name: 'GITHUB_ACCESS_TOKEN',
                description: '',
            },
        ],
    },
    radar: [
        {
            source: ['github.com/notifications'],
        },
    ],
    name: 'Notifications',
    maintainers: ['zhzy0077'],
    handler,
    url: 'github.com/notifications',
};

async function handler(ctx) {
    if (!config.github || !config.github.access_token) {
        throw new ConfigNotFoundError('GitHub notification RSS is disabled due to the lack of <a href="https://docs.rsshub.app/deploy/config#route-specific-configurations">relevant config</a>');
    }
    const headers = {
        Accept: 'application/vnd.github.v3+json',
        Authorization: `Bearer ${config.github.access_token}`,
        'X-GitHub-Api-Version': '2022-11-28',
    };

    const response = await ofetch.raw(`${apiUrl}/notifications`, {
        headers,
    });
    const notifications = response._data;

    const items = notifications.map((item) => {
        let originUrl = item.subject.url ? item.subject.url.replace('https://api.github.com/repos/', 'https://github.com/') : 'https://github.com/notifications';
        if (originUrl.includes('/releases/')) {
            originUrl = originUrl.replace(/\/releases\/\d+$/, '/releases');
        } else if (originUrl.includes('/pulls/')) {
            originUrl = originUrl.replace(/\/pulls\/(\d+)$/, '/pull/$1');

View on GitHub (pinned to bed535e087)

Solutions

  1. Set GITHUB_ACCESS_TOKEN to a personal access token that has the 'notifications' scope enabled
  2. For classic PATs: check 'notifications' under personal access token settings when creating the token
  3. For fine-grained PATs: grant 'Notifications' -> Read access under account permissions
  4. Restart RSSHub after updating the token

Example fix

// Configuration fix:
// 1. Create a GitHub PAT with 'notifications' scope
// 2. Set GITHUB_ACCESS_TOKEN=ghp_xxxx
// 3. Restart RSSHub
Defensive patterns

Strategy: validation

Validate before calling

// Verify token has notifications scope before the route handler runs
if (!config.github?.access_token) {
    throw new ConfigNotFoundError('GITHUB_ACCESS_TOKEN is required for notifications. Token must have notifications scope.');
}

Type guard

function hasGitHubToken(cfg: typeof config): cfg is typeof config & { github: { access_token: string } } {
    return !!cfg.github?.access_token;
}

Prevention

When it happens

Trigger: Any request to /github/notifications when GITHUB_ACCESS_TOKEN is not set. Even if set, the token must have the 'notifications' scope or the downstream API call will return 401/403. The guard fires before any network call.

Common situations: GITHUB_ACCESS_TOKEN not set at all; token exists but lacks the 'notifications' scope (classic PAT needs 'notifications' checked, fine-grained PAT needs 'Notifications' read access); the user expects public data but notifications are inherently private.

Related errors


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