badges/shields · error · InvalidParameter

invalid magazine

Error message

invalid magazine

What it means

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.

Source

Thrown at services/mbin/mbin.service.js:48

    },
  }

  static defaultBadgeData = { label: 'magazine', namedLogo: 'activitypub' }

  static render({ magazine, members }) {
    return {
      label: `subscribe to ${magazine}`,
      message: metric(members),
      style: 'social',
      color: 'brightgreen',
    }
  }

  async fetch({ magazine }) {
    const splitAlias = magazine.split('@')
    // The magazine will be in the format of 'magazine@server'
    if (splitAlias.length !== 2) {
      throw new InvalidParameter({
        prettyMessage: 'invalid magazine',
      })
    }

    const mag = splitAlias[0]
    const host = splitAlias[1]

    const data = await this._requestJson({
      url: `https://${host}/api/magazine/name/${mag}`,
      schema,
      httpErrors: {
        404: 'magazine not found',
      },
    })

    return data.subscriptionsCount
  }

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. Pass the magazine as 'name@instance', e.g. 'technology@lemmy.world'
  2. Strip any leading '!' or '@' prefix and any path/URL decoration, keeping only name@host
  3. Ensure the name part is non-empty and there is exactly one '@'
  4. URL-encode properly if the alias is embedded in a generated link

Example fix

// before
/mbin/subscribers/foo
// after
/mbin/subscribers/foo@kbin.social
Defensive patterns

Strategy: validation

Validate before calling

const parts = String(magazine).split('@')
if (parts.length !== 2 || !parts[0] || !parts[1]) {
  throw new Error(`magazine must be 'name@instance', got: ${magazine}`)
}

Type guard

function isValidMagazineAlias(v) {
  if (typeof v !== 'string') return false
  const [name, host] = v.split('@')
  return v.split('@').length === 2 && name.length > 0 && /^[\w.-]+$/.test(host)
}

Try / catch

try {
  return await mbinBadge({ magazine })
} catch (e) {
  if (e instanceof InvalidParameter && e.message === 'invalid magazine') {
    console.error(`Fix magazine alias format: 'name@instance' (got '${magazine}')`)
    return null
  }
  throw e
}

Prevention

When it happens

Trigger: 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`.

Common situations: 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.

Related errors


AI-assisted analysis of badges/shields@766fd8bc89 (2026-08-30). Data as JSON: /api/errors/ca44b0157ba8beb5. Report an issue: GitHub.