badges/shields · error · ImproperlyConfigured

Unable to select next Libraries.io token from pool

Error message

Unable to select next Libraries.io token from pool

What it means

Libraries.io requests in Shields use a pool of API tokens that are rotated to spread rate limits. When withPooling is enabled, the service pulls the next token from StandardTokens.next(); if that call throws (e.g. no tokens are available or the pool is misconfigured), the error is wrapped in an ImproperlyConfigured with this message. It is a service configuration problem, not a network or user error.

Source

Thrown at services/librariesio/librariesio-api-provider.js:79

  updateToken({ token, res }) {
    const { totalUsesRemaining, nextReset } = this.getRateLimitFromHeaders({
      headers: res.headers,
      token,
    })
    token.update(totalUsesRemaining, nextReset)
  }

  async fetch(requestFetcher, url, options = {}) {
    const { baseUrl } = this

    let token
    let tokenString
    if (this.withPooling) {
      try {
        token = this.standardTokens.next()
      } catch (e) {
        log.error(e)
        throw new ImproperlyConfigured({
          prettyMessage: 'Unable to select next Libraries.io token from pool',
        })
      }
      tokenString = token.id
    } else {
      tokenString = this.globalToken
    }

    const mergedOptions = {
      ...options,
      ...{
        headers: {
          'User-Agent': userAgent,
          ...options.headers,
        },
        searchParams: {
          api_key: tokenString,
          ...options.searchParams,

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. Add at least one valid Libraries.io API token to the configured token pool (env/config).
  2. If you only have one token, disable pooling and set globalToken instead.
  3. Verify the token pool module (StandardTokens) is constructed with the configured credentials and that token entries have an id field.
  4. Regenerate the Libraries.io API key if existing tokens were revoked.

Example fix

// before
withPooling: true  // but no tokens in pool
// after
withPooling: false,
globalToken: process.env.LIBRARIES_IO_TOKEN
Defensive patterns

Strategy: try-catch

Validate before calling

if (!tokens || tokens.length === 0) throw new Error('Libraries.io token pool is empty; configure LIBRARIES_IO_TOKEN')

Type guard

null

Try / catch

try {
  const badge = await librariesioProvider.fetch(params)
} catch (e) {
  if (e instanceof ImproperlyConfigured && e.prettyMessage.includes('token')) {
    // fix config: supply/rotate Libraries.io tokens, then retry
  }
  throw e
}

Prevention

When it happens

Trigger: Instantiating the Libraries.io provider with withPooling=true but an empty or invalid token pool, so standardTokens.next() throws when fetch() selects a token.

Common situations: Deploying without configuring the Libraries.io token pool in the environment, all configured tokens having been removed or invalidated, or accidentally enabling pooling when only a single global token is set.

Related errors


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