{"record":{"id":"25a2a4c3507edee6","repo":"anuraghazra/github-readme-stats","slug":"missing-params-username-make-sure-you-pass-the-p-25a2a4","errorCode":null,"errorMessage":"Missing params \"username\" make sure you pass the parameters in URL","messagePattern":"Missing params \"username\" make sure you pass the parameters in URL","errorType":"validation","errorClass":"MissingParamError","httpStatus":null,"severity":"warning","filePath":"src/fetchers/wakatime.js","lineNumber":14,"sourceCode":"// @ts-check\n\nimport axios from \"axios\";\nimport { CustomError, MissingParamError } from \"../common/error.js\";\n\n/**\n * WakaTime data fetcher.\n *\n * @param {{username: string, api_domain: string }} props Fetcher props.\n * @returns {Promise<import(\"./types\").WakaTimeData>} WakaTime data response.\n */\nconst fetchWakatimeStats = async ({ username, api_domain }) => {\n  if (!username) {\n    throw new MissingParamError([\"username\"]);\n  }\n\n  try {\n    const { data } = await axios.get(\n      `https://${\n        api_domain ? api_domain.replace(/\\/$/gi, \"\") : \"wakatime.com\"\n      }/api/v1/users/${username}/stats?is_including_today=true`,\n    );\n\n    return data.data;\n  } catch (err) {\n    if (err.response.status < 200 || err.response.status > 299) {\n      throw new CustomError(\n        `Could not resolve to a User with the login of '${username}'`,\n        \"WAKATIME_USER_NOT_FOUND\",\n      );\n    }\n    throw err;","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/anuraghazra/github-readme-stats/blob/54a7985aeefda00d5eadb55b80c17c7f976c37d2/src/fetchers/wakatime.js#L1-L32","documentation":"Thrown by fetchWakatimeStats when the destructured username is falsy. Unlike the top-languages fetcher, this function takes an object ({ username, api_domain }), so the missing key yields undefined. The check `if (!username)` fires before the axios call, so this is a pure caller-contract error, identical in message to the top-languages variant because both use the shared MissingParamError class.","triggerScenarios":"Calling fetchWakatimeStats({}) or fetchWakatimeStats({ username: \"\" }). Via the HTTP API (api/wakatime.js:82), a GET /api/wakatime request that omits ?username= or passes ?username= empty, so req.query.username is undefined when the handler calls fetchWakatimeStats({ username, api_domain }).","commonSituations":"A WakaTime card URL missing the ?username= parameter; a template variable that was never substituted; a programmatic caller building the props object from a config that lacks the username field.","solutions":["Include a non-empty ?username=<wakatime-login> in the request URL, e.g. /api/wakatime?username=johndoe.","When calling fetchWakatimeStats directly, pass { username: validatedNonEmptyString } in the props object.","Validate the username at the API boundary and return a descriptive 400 before reaching the fetcher."],"exampleFix":"// before\nconst stats = await fetchWakatimeStats({ username: req.query.username, api_domain });\n\n// after\nconst username = req.query.username;\nif (!username || !username.trim()) {\n  return res.status(400).send(\"username query parameter is required\");\n}\nconst stats = await fetchWakatimeStats({ username: username.trim(), api_domain });","handlingStrategy":"validation","validationCode":"// Validate the props object before invoking fetchWakatimeStats\nfunction buildWakatimeProps(query) {\n  const username = query?.username;\n  if (typeof username !== \"string\" || username.trim() === \"\") {\n    throw new Error(\"'username' is required for WakaTime stats\");\n  }\n  return { username: username.trim(), api_domain: query?.api_domain };\n}\n\nconst props = buildWakatimeProps(req.query);\nconst stats = await fetchWakatimeStats(props);","typeGuard":"/** @param {unknown} p */\nfunction hasUsername(p) {\n  return typeof p === \"object\" && p !== null &&\n    typeof p.username === \"string\" && p.username.trim().length > 0;\n}\n\nif (!hasUsername(props)) {\n  return res.status(400).send(\"username query parameter is required\");\n}","tryCatchPattern":"try {\n  const stats = await fetchWakatimeStats({ username, api_domain });\n} catch (err) {\n  if (err instanceof MissingParamError && err.missedParams.includes(\"username\")) {\n    return res.status(400).send(err.message); // bad request, no retry\n  }\n  throw err;\n}","preventionTips":["Validate the username query param at the API boundary before constructing the fetcher props.","Since the fetcher takes an object, build that object in one place with validation to avoid missing keys.","Cover the missing-username case in tests so the 400 path stays working."],"tags":["validation","params","user-input","wakatime"],"backgroundTag":null,"analyzedSha":"54a7985aeefda00d5eadb55b80c17c7f976c37d2","analyzedAt":"2026-08-12T23:20:41.776Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}