DIYgod/RSSHub · error · ConfigNotFoundError
Readwise access token is missing
Error message
Readwise access token is missing
What it means
The Readwise list route needs a personal access token under `config.readwise.accessToken` to authenticate against `readwise.io/api/v3/list/`. If `config.readwise` itself is undefined or its `accessToken` is empty, the handler refuses to run — Readwise returns 401 for any unauthenticated call and there is no public fallback. This is the only entry point for the route.
Source
Thrown at lib/routes/readwise/list.ts:65
\`\`\`
https://rsshub.app/readwise/list/location=new&category=article
\`\`\`
fetches articles in the Inbox.
\`\`\`
https://rsshub.app/readwise/list/category=article&tag=shortlist&tag=AI&tagStrategy=all
\`\`\`
fetches articles tagged both by \`shortlist\` and \`AI\`.`,
};
const TAG_STRATEGY_ALL = 'all'; // Items with tags matching all the given ones can then be returned.
const TAG_STRATEGY_ANY = 'any'; // Items with tags matching any of the given ones can be returned.
async function handler(ctx) {
if (!config.readwise || !config.readwise.accessToken) {
throw new ConfigNotFoundError('Readwise access token is missing');
}
let apiUrl = 'https://readwise.io/api/v3/list/?';
let tag, tagStrategy;
if (ctx.req.param('routeParams')) {
const urlSearchParams = new URLSearchParams(ctx.req.param('routeParams'));
const location = urlSearchParams.get('location');
const category = urlSearchParams.get('category');
const updatedAfter = urlSearchParams.get('updatedAfter');
tag = urlSearchParams.get('tag');
tagStrategy = urlSearchParams.get('tagStrategy') === TAG_STRATEGY_ANY || urlSearchParams.get('tagStrategy') === TAG_STRATEGY_ALL ? urlSearchParams.get('tagStrategy') : TAG_STRATEGY_ANY;
if (location) {
apiUrl += `location=${location}&`;
}View on GitHub (pinned to bed535e087)
Solutions
- Generate a Readwise access token at https://readwise.io/access_token and set `READWISE_ACCESS_TOKEN=<token>` in the RSSHub environment, then restart.
- Verify the config block exists; if you load config from a custom file, ensure the `readwise.accessToken` path is populated.
- If you do not have an account, the route is simply unavailable — Readwise has no anonymous API.
Example fix
// before # no readwise config // after # .env READWISE_ACCESS_TOKEN=xxxxxxxxxxxxxxxx
Defensive patterns
Strategy: validation
Validate before calling
if (!config.readwise?.accessToken) {
return ctx.body('Readwise route requires READWISE_ACCESS_TOKEN.', 503);
} Type guard
const hasReadwiseToken = (c: typeof config): boolean => Boolean(c.readwise?.accessToken);
Prevention
- Store the token in a secret manager, not in plaintext config files.
- Document the token acquisition URL (https://readwise.io/access_token) next to the route.
- Add a startup self-test that pings /api/v3/auth/ with the configured token.
When it happens
Trigger: A request to /readwise/list/... on an RSSHub instance where `READWISE_ACCESS_TOKEN` was never set. The check runs before any URLSearchParams parsing or API call.
Common situations: Self-hosted deploy that skipped the Readwise config block; user assumed the public rsshub.app instance ships with shared credentials (it does not — each user needs their own token); token name typo in env (`READWISE_TOKEN` instead of `READWISE_ACCESS_TOKEN`).
Related errors
- QWeather RSS is disabled due to the lack of <a href="https:/
- QWeather RSS is disabled due to the lack of <a href="https:/
- Skeb followings RSS is disabled due to the lack of relevant
- Skeb followings RSS is disabled due to the lack of relevant
- Skeb followings RSS is disabled due to the lack of relevant
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/4a92c827ca89c3b5.
Report an issue: GitHub.