{"record":{"id":"088b4131df87dc9a","repo":"DIYgod/RSSHub","slug":"last-fm-rss-is-disabled-due-to-the-lack-of-a-href-088b41","errorCode":null,"errorMessage":"Last.fm RSS is disabled due to the lack of <a href=\"https://docs.rsshub.app/deploy/config#route-specific-configurations\">relevant config</a>","messagePattern":"Last\\.fm RSS is disabled due to the lack of <a href=\"https://docs\\.rsshub\\.app/deploy/config#route-specific-configurations\">relevant config</a>","errorType":"exception","errorClass":null,"httpStatus":503,"severity":"error","filePath":"lib/routes-deprecated/lastfm/top.js","lineNumber":6,"sourceCode":"const got = require('@/utils/got');\nconst config = require('@/config').value;\n\nmodule.exports = async (ctx) => {\n    if (!config.lastfm || !config.lastfm.api_key) {\n        throw new Error('Last.fm RSS is disabled due to the lack of <a href=\"https://docs.rsshub.app/deploy/config#route-specific-configurations\">relevant config</a>');\n    }\n\n    const country = ctx.params.country;\n    const api_key = config.lastfm.api_key;\n\n    const response = await got(`http://ws.audioscrobbler.com/2.0/?method=${country ? 'geo.gettoptracks' : 'chart.gettoptracks'}${country ? '&country=' + country : ''}&api_key=${api_key}&format=json`);\n    const data = response.data;\n    const list = data.tracks.track;\n\n    ctx.state.data = {\n        title: `Top Tracks${country ? ' in ' + data.tracks['@attr'].country : ''} - Last.fm`,\n        link: 'https://www.last.fm/charts#top-tracks',\n        item: list.map((item) => ({\n            title: `${item.name} - ${item.artist.name}`,\n            author: item.artist.name,\n            description: `<img src=\"${item.image.at(-1)['#text']}\" />`,\n            pubDate: new Date(),\n            link: item.url,","sourceCodeStart":1,"sourceCodeEnd":24,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes-deprecated/lastfm/top.js#L1-L24","documentation":"Thrown by the Last.fm top-tracks route (deprecated) when config.lastfm.api_key is missing. Same guard as the other Last.fm routes; the route calls either chart.gettoptracks or geo.gettoptracks depending on whether a :country param is present, both requiring the key.","triggerScenarios":"Request to the top-tracks route (with or without country) while LASTFM_API_KEY is unset; guard throws before the audioscrobbler call.","commonSituations":"Same as sibling Last.fm routes: unconfigured deployment, env var not propagated, or config block absent. Because this route optionally takes a country param, callers sometimes assume no key is needed — it is always needed.","solutions":["Set LASTFM_API_KEY and restart RSSHub.","Confirm the key works by calling http://ws.audioscrobbler.com/2.0/?method=chart.gettoptracks&api_key=<key>&format=json directly.","Apply the same key to all three Last.fm routes (loved, recent, top)."],"exampleFix":"// env\n// before\n# LASTFM_API_KEY not set\n// after\nLASTFM_API_KEY=<your_key>","handlingStrategy":"validation","validationCode":"if (!process.env.LASTFM_API_KEY) {\n  throw new Error('LASTFM_API_KEY required for top-tracks (with or without country)');\n}","typeGuard":"const hasLastfmConfig = (c: { lastfm?: { api_key?: string } }): boolean =>\n  Boolean(c.lastfm?.api_key);","tryCatchPattern":"try { await rsshub('/lastfm/top' + (country ? '/' + country : '')); }\ncatch (e) {\n  if (/disabled due to the lack/.test(e.message)) return configureKey();\n  throw e;\n}","preventionTips":["Country param is optional but the key never is.","Smoke-test the key against the audioscrobbler endpoint directly."],"tags":["rsshub","missing-config","api-key","lastfm","deprecated-route"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}