badges/shields · error · InvalidResponse

invalid response data from auth endpoint

Error message

invalid response data from auth endpoint

What it means

_getJwtExpiry splits the JWT on '.' and requires at least two segments (header.payload) to read the expiry claim. If the token does not look like a JWT, it throws InvalidResponse 'invalid response data from auth endpoint', meaning the auth endpoint returned something other than a well-formed token (capped at the `max` expiry).

Source

Thrown at core/base-service/auth-helper.js:239

      ...rest,
    }
  }

  withQueryStringAuth({ userKey, passKey }, requestParams) {
    return this._withAnyAuth(requestParams, requestParams =>
      this.constructor._mergeQueryParams(requestParams, {
        ...(userKey ? { [userKey]: this._user } : undefined),
        ...(passKey ? { [passKey]: this._pass } : undefined),
      }),
    )
  }

  static _getJwtExpiry(token, max = dayjs().add(1, 'hours').unix()) {
    // get the expiry timestamp for this JWT (capped at a max length)
    const parts = token.split('.')

    if (parts.length < 2) {
      throw new InvalidResponse({
        prettyMessage: 'invalid response data from auth endpoint',
      })
    }

    const json = validate(
      {
        ErrorClass: InvalidResponse,
        prettyErrorMessage: 'invalid response data from auth endpoint',
      },
      parseJson(Buffer.from(parts[1], 'base64').toString()),
      Joi.object({ exp: Joi.number().required() }).required(),
    )

    return Math.min(json.exp, max)
  }

  static _isJwtValid(expiry) {
    // we consider the token valid if the expiry

View on GitHub (pinned to 766fd8bc89)

Solutions

  1. Verify the login endpoint URL is correct and returns JSON containing a real JWT
  2. Check credentials — failed logins often return HTML/error bodies instead of tokens
  3. Log/inspect the raw response from the auth endpoint to see what 'token' actually contains
  4. Update the service integration if the auth API's response format changed

Example fix

// before
const { token } = await getAuthToken() // token = '<html>login page</html>'
const expiry = _getJwtExpiry(token) // throws
// after
const auth = await getAuthToken()
if (typeof auth.token !== 'string' || auth.token.split('.').length < 2) throw new Error('auth endpoint did not return a JWT')
const expiry = _getJwtExpiry(auth.token)
Defensive patterns

Strategy: try-catch

Validate before calling

function looksLikeJwt(token) {
  return typeof token === 'string' && token.trim().length > 0 && token.split('.').length >= 2 && !token.startsWith('<')
}
if (!looksLikeJwt(tokenFromAuthEndpoint)) throw new Error('auth endpoint did not return a JWT')

Type guard

function isJwt(value) {
  return typeof value === 'string' && value.split('.').length >= 2 &&
    value.split('.').every(p => p.length > 0) && !/[<\s]/.test(value)
}
if (isJwt(token)) { /* safe to read expiry */ }

Try / catch

try {
  const expiry = AuthHelper._getJwtExpiry(token)
} catch (err) {
  if (err.prettyMessage === 'invalid response data from auth endpoint') {
    // inspect raw auth response, refresh credentials or fix endpoint
  } else throw err
}

Prevention

When it happens

Trigger: The response from the login/auth endpoint yielded a `token` value with fewer than two dot-separated segments — e.g. an HTML login page, a JSON error body passed through, an empty string, or an opaque API key mistakenly used where a JWT is expected.

Common situations: Auth endpoint changed its response shape after a version upgrade; wrong credentials returning an error page instead of a token; proxy/captive portal returning HTML; config pointing at the wrong login endpoint path.

Related errors


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