{"record":{"id":"31fceacf41e32409","repo":"BabylonJS/Babylon.js","slug":"no-avatar-found-for-forum-user-username","errorCode":null,"errorMessage":"No avatar found for forum user \"${username}\"","messagePattern":"No avatar found for forum user \"(.+?)\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/inspector-v2/scripts/makeAvatar.mjs","lineNumber":65,"sourceCode":"                return;\r\n            }\r\n            if (res.statusCode !== 200) {\r\n                reject(new Error(`HTTP ${res.statusCode} for ${url}`));\r\n                return;\r\n            }\r\n            const chunks = [];\r\n            res.on(\"data\", (chunk) => chunks.push(chunk));\r\n            res.on(\"end\", () => resolve(Buffer.concat(chunks)));\r\n            res.on(\"error\", reject);\r\n        }).on(\"error\", reject);\r\n    });\r\n}\r\n\r\nasync function fetchForumAvatarUrl(username, size = 96) {\r\n    const userJson = JSON.parse((await fetchUrl(`https://forum.babylonjs.com/u/${username}.json`)).toString(\"utf-8\"));\r\n    const avatarTemplate = userJson.user?.avatar_template;\r\n    if (!avatarTemplate) {\r\n        throw new Error(`No avatar found for forum user \"${username}\"`);\r\n    }\r\n    const relativePath = avatarTemplate.replace(\"{size}\", String(size));\r\n    return `https://forum.babylonjs.com${relativePath}`;\r\n}\r\n\r\nconst isUrl = /^https?:\\/\\//i.test(inputPath);\r\nconst isFilePath = !isUrl && (inputPath.includes(\"/\") || inputPath.includes(\"\\\\\") || existsSync(resolve(inputPath)));\r\n\r\nlet inputBuffer;\r\nif (isUrl) {\r\n    inputBuffer = await fetchUrl(inputPath);\r\n} else if (isFilePath) {\r\n    inputBuffer = await readFile(resolve(inputPath));\r\n} else {\r\n    // Treat as a Babylon.js forum username\r\n    const avatarUrl = await fetchForumAvatarUrl(inputPath);\r\n    inputBuffer = await fetchUrl(avatarUrl);\r\n}\r","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/inspector-v2/scripts/makeAvatar.mjs#L47-L83","documentation":"This build-time script resolves a forum user's avatar by fetching https://forum.babylonjs.com/u/<username>.json and reading user.avatar_template. It throws when the Discourse API response contains no avatar_template, i.e. the username does not exist or the profile exposes no avatar.","triggerScenarios":"Running makeAvatar.mjs with a username that has no forum account, a typo'd handle, a deleted/suspended account, or a forum API response lacking user.avatar_template (private or restricted profile).","commonSituations":"Contributor avatar generation in CI where a listed username was changed or deleted; typos in the contributors list; forum rate-limiting or API shape changes returning unexpected JSON.","solutions":["Verify the username exists by visiting https://forum.babylonjs.com/u/<username> and correct the spelling in the input.","If the account was renamed/deleted, update the contributor data to the current username or remove the entry.","Check the raw JSON endpoint (/u/<username>.json) to confirm avatar_template is present; if API shape changed, update the parsing logic.","Add retry/backoff if the forum API rate-limits the request in CI."],"exampleFix":"// before\nnode makeAvatar.mjs jonathanibany  // typo'd username\n// after\nnode makeAvatar.mjs JCPalmer  // verified existing forum username\n// or fetch the profile first to confirm:\n// curl https://forum.babylonjs.com/u/<username>.json","handlingStrategy":"retry","validationCode":"async function forumUserExists(username: string): Promise<boolean> {\n  const res = await fetch(`https://forum.babylonjs.com/u/${encodeURIComponent(username)}.json`);\n  if (!res.ok) return false;\n  const json = await res.json();\n  return !!json?.user?.avatar_template;\n}","typeGuard":"function hasAvatarTemplate(u: unknown): u is { user: { avatar_template: string } } {\n  return typeof (u as any)?.user?.avatar_template === \"string\";\n}","tryCatchPattern":"try {\n  const url = await fetchForumAvatarUrl(username);\n} catch (e) {\n  if (e instanceof Error && e.message.includes(\"No avatar found for forum user\")) {\n    console.warn(`Skipping ${username}: no forum avatar; using default avatar.`);\n  } else throw e;\n}","preventionTips":["Validate usernames against the live forum before running avatar generation","Use encodeURIComponent on usernames in URLs","Keep the contributor list in sync with current forum handles","Add CI fallback to a default avatar instead of failing the whole build"],"tags":["script","network","avatar","discourse-api"],"backgroundTag":"missing-user-profile","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}