sahat/hackathon-starter · error · Error

HTTP error! status: ${response.status}

Error message

HTTP error! status: ${response.status}

What it means

After a successful Tumblr OAuth 1.0a login, the strategy fetches https://api.tumblr.com/v2/user/info with a signed header and throws on any non-2xx HTTP status.

Source

Thrown at config/passport.js:605

      state: true,
      passReqToCallback: true,
    },
    async (req, token, tokenSecret, profile, done) => {
      try {
        if (!token || !tokenSecret) {
          throw new Error('Missing or invalid token/tokenSecret');
        }
        // Helper function to generate the OAuth 1.0a authHeader for Tumblr API.
        // This function is not going to make any actual calls to
        // tumblr's /request_token or /access_token endpoints.
        function getTumblrAuthHeader(url, method) {
          const oauth = new OAuth('https://www.tumblr.com/oauth/request_token', 'https://www.tumblr.com/oauth/access_token', process.env.TUMBLR_KEY, process.env.TUMBLR_SECRET, '1.0A', null, 'HMAC-SHA1');
          return oauth.authHeader(url, token, tokenSecret, method);
        }
        const userInfoURL = 'https://api.tumblr.com/v2/user/info';
        const response = await fetch(userInfoURL, { headers: { Authorization: getTumblrAuthHeader(userInfoURL, 'GET') } });
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json();
        // Extract user info from the API response
        const tumblrUser = data.response.user;
        const primaryBlog = tumblrUser.blogs?.find((blog) => blog.primary) || tumblrUser.blogs?.[0];
        const providerProfile = {
          id: primaryBlog.uuid || tumblrUser.name,
          name: tumblrUser.name,
          picture: primaryBlog?.avatar?.[0]?.url,
          website: primaryBlog?.url,
        };
        try {
          const sessionAlreadyLoggedIn = !!req.user;
          const user = await handleAuthLogin(req, token, null, 'tumblr', {}, providerProfile, sessionAlreadyLoggedIn, tokenSecret, false);
          if (sessionAlreadyLoggedIn && req.user.id === user.id) {
            req.flash('info', { msg: 'Tumblr account has been linked.' });
          }
          return done(null, user);

View on GitHub (pinned to c12e339564)

Solutions

  1. Check response.status in server logs: 401 → re-authorize the app (unlink/relink); 429 → back off and retry
  2. Verify system clock is accurate (OAuth 1.0a timestamps are sensitive)
  3. Confirm TUMBLR_KEY/TUMBLR_SECRET in .env still match the registered Tumblr app

Example fix

// before
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
// after
if (!response.ok) return done(null, false, { msg: `Tumblr API returned ${response.status}. Try relinking your account.` });
Defensive patterns

Strategy: retry

Try / catch

catch (e) { if (/HTTP error! status: (401|429)/.test(e.message)) { /* re-auth or backoff */ } throw e; }

Prevention

When it happens

Trigger: Tumblr's user/info endpoint returns 401 (bad signature/expired token), 429 (rate limit), or 5xx during the verify callback of the Tumblr strategy.

Common situations: System clock skew breaking the HMAC-SHA1 signed header, revoked or expired access token, TUMBLR_KEY changed since the token was issued, or Tumblr API downtime/rate limiting.

Related errors


AI-assisted analysis of sahat/hackathon-starter@c12e339564 (2026-08-27). Data as JSON: /api/errors/c540fbcab3478889. Report an issue: GitHub.