{"record":{"id":"ca44b0157ba8beb5","repo":"badges/shields","slug":"invalid-magazine","errorCode":null,"errorMessage":"invalid magazine","messagePattern":"invalid magazine","errorType":"exception","errorClass":"InvalidParameter","httpStatus":null,"severity":"error","filePath":"services/mbin/mbin.service.js","lineNumber":48,"sourceCode":"    },\n  }\n\n  static defaultBadgeData = { label: 'magazine', namedLogo: 'activitypub' }\n\n  static render({ magazine, members }) {\n    return {\n      label: `subscribe to ${magazine}`,\n      message: metric(members),\n      style: 'social',\n      color: 'brightgreen',\n    }\n  }\n\n  async fetch({ magazine }) {\n    const splitAlias = magazine.split('@')\n    // The magazine will be in the format of 'magazine@server'\n    if (splitAlias.length !== 2) {\n      throw new InvalidParameter({\n        prettyMessage: 'invalid magazine',\n      })\n    }\n\n    const mag = splitAlias[0]\n    const host = splitAlias[1]\n\n    const data = await this._requestJson({\n      url: `https://${host}/api/magazine/name/${mag}`,\n      schema,\n      httpErrors: {\n        404: 'magazine not found',\n      },\n    })\n\n    return data.subscriptionsCount\n  }\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/services/mbin/mbin.service.js#L30-L66","documentation":"The Mbin service expects the `magazine` route parameter in the federated form 'magazine@server' (exactly one '@' separating local name and instance host). fetch() splits on '@' and throws InvalidParameter if the split does not yield exactly two parts. This guards against bare magazine names, fully-qualified URLs, or stray '@' characters reaching the upstream API call.","triggerScenarios":"Requesting a badge with `magazine=foo` (no @instance), `magazine=@instance` (empty name), `magazine=foo@bar@baz` (multiple @), or a URL-encoded full URL like `https%3A%2F%2Fmbin.example%2Fm%2Ffoo`.","commonSituations":"Copy-pasting a magazine URL instead of its alias; omitting the instance when the magazine lives on another server; ActivityPub-style handle confusion between '!' and '@' prefixes.","solutions":["Pass the magazine as 'name@instance', e.g. 'technology@lemmy.world'","Strip any leading '!' or '@' prefix and any path/URL decoration, keeping only name@host","Ensure the name part is non-empty and there is exactly one '@'","URL-encode properly if the alias is embedded in a generated link"],"exampleFix":"// before\n/mbin/subscribers/foo\n// after\n/mbin/subscribers/foo@kbin.social","handlingStrategy":"validation","validationCode":"const parts = String(magazine).split('@')\nif (parts.length !== 2 || !parts[0] || !parts[1]) {\n  throw new Error(`magazine must be 'name@instance', got: ${magazine}`)\n}","typeGuard":"function isValidMagazineAlias(v) {\n  if (typeof v !== 'string') return false\n  const [name, host] = v.split('@')\n  return v.split('@').length === 2 && name.length > 0 && /^[\\w.-]+$/.test(host)\n}","tryCatchPattern":"try {\n  return await mbinBadge({ magazine })\n} catch (e) {\n  if (e instanceof InvalidParameter && e.message === 'invalid magazine') {\n    console.error(`Fix magazine alias format: 'name@instance' (got '${magazine}')`)\n    return null\n  }\n  throw e\n}","preventionTips":["Normalize input: strip leading '!' or '@', extract name and host from URLs before joining with '@'","Validate the alias with a regex ^[^@\\s]+@[^@\\s]+$ before display or API use","Keep a canonical list of magazine aliases instead of accepting arbitrary user text","Remember federated handles need the instance part; a bare name is never valid"],"tags":["invalid-parameter","federation","input-format","mbin"],"backgroundTag":"invalid-identifier-format","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}