---
title: "Meta & LinkedIn API Error 401: Expired Token & How to Fix It"
description: "Meta and LinkedIn access tokens expire on a strict TTL, and manual refresh workers can hit race conditions. Ayrshare explains why, and how to avoid it entirely."
canonical: https://www.ayrshare.com/solutions/meta-linkedin-api-error-401-expired-token-how-to-fix-it/
lastModified: 2026-07-09
pageType: solution
---

# Meta & LinkedIn API Error 401: Expired Token & How to Fix It

> Meta and LinkedIn access tokens expire on a strict TTL, and manual refresh workers can hit race conditions. Ayrshare explains why, and how to avoid it entirely.

## Meta & LinkedIn API Error 401: Expired Token & How to Fix It

[Start free trial](https://app.ayrshare.com)
[View pricing](/pricing/)

You've got your OAuth 2.0 flow perfectly wired. Users are authenticating, your app is publishing content, and your backend is humming along happily for exactly two months. Then, your monitoring channels violently wake you up. Every outgoing request to Meta or LinkedIn is suddenly bouncing back with an HTTP 401 Unauthorized or a 190 OAuthException.

The user didn't revoke permissions. You just slammed into the strict, non-negotiable wall of social media token expiration.

## The "Why" Behind the 401 Unauthorized

Social platforms are ruthlessly protective of user access, meaning they aggressively limit the TTL (Time To Live) of their authorization payloads.

When a user initially authenticates with Meta, the platform issues a short-lived token valid for barely an hour. You must immediately perform a Token Exchange to convert it into Long lived access tokens (valid for about 60 days). LinkedIn skips the short-lived step but strictly enforces a 60-day expiration on access tokens, issuing a 1-year refresh token alongside it.

When that 60-day TTL runs out, the token is dead. To avoid an outage, you have to build a stateful background worker that tracks expiration timestamps and pings the native refresh tokens API before the token expires. Furthermore, if you run multiple instances of your app and two workers attempt to refresh the same token simultaneously, you'll create a race condition that invalidates the entire token chain.

## The Manual Fix: Atomic Token Rotation

To solve this natively, you need to build an atomic refresh function. Here is a Node.js implementation using Redis to lock the refresh process, ensuring only one worker safely exchanges a Meta short-lived token for a 60-day long-lived token.

```javascript
const axios = require("axios");
const Redis = require("ioredis");
const redis = new Redis();

const APP_ID = "your_meta_app_id";
const APP_SECRET = "your_meta_app_secret";

// Safely rotates a Meta token without triggering race conditions
async function refreshLongLivedToken(userId, currentToken) {
  const lockKey = `token_refresh_lock:${userId}`;

  // 1. Acquire an atomic lock (expires in 10 seconds to prevent deadlocks)
  const acquired = await redis.set(lockKey, "LOCKED", "NX", "EX", 10);
  if (!acquired) {
    throw new Error("Token Exchange is already in progress by another worker.");
  }

  try {
    // 2. Hit the native refresh tokens API
    const response = await axios.get("https://graph.facebook.com/v19.0/oauth/access_token", {
      params: {
        grant_type: "fb_exchange_token",
        client_id: APP_ID,
        client_secret: APP_SECRET,
        fb_exchange_token: currentToken
      }
    });

    const newLongLivedToken = response.data.access_token;
    const expiresInSeconds = response.data.expires_in;

    // 3. Persist the new token and its exact TTL to your primary database here
    await updateDatabase(userId, newLongLivedToken, expiresInSeconds);

    return newLongLivedToken;
  } catch (error) {
    console.error("Token Exchange failed:", error.response?.data || error.message);
    throw error;
  } finally {
    // 4. Release the lock
    await redis.del(lockKey);
  }
}
```

## The Pivot: Stop Babysitting OAuth States

Writing distributed locking mechanisms and running daily CRON jobs just to maintain an active connection to an API is a massive engineering distraction. You are building a product, not an OAuth 2.0 state machine.

This is exactly why our team at Ayrshare built our platform. We act as your ultimate API insurance policy. When you use Ayrshare to connect your users' social accounts, we handle the entire token lifecycle. We track the TTL securely on our end, automatically perform the Token Exchange in the background, and seamlessly cycle in fresh Long lived access tokens without you ever having to write a single line of CRON logic.

You send the content; we guarantee the authorization state is always valid.

For more detail, see [Facebook Linking](/docs/dashboard/connect-social-accounts/facebook).

## The Comparison: Native vs. Ayrshare

Here is how your publishing logic transforms when you stop managing token databases and offload the complexity to us.

### Before (Native API + Cron)

```javascript
// You must constantly pull auth state, check TTLs, and handle manual retries.
const authState = await getUserAuthFromDB(userId);

if (Date.now() >= authState.expiresAt - (7 * 24 * 60 * 60 * 1000)) {
  // Token expires in less than 7 days. Manually refresh it before posting.
  authState.token = await refreshLongLivedToken(userId, authState.token);
}

const response = await axios.post(
  `https://graph.facebook.com/v19.0/${userId}/feed`,
  { message: "Hello World" },
  { headers: { Authorization: `Bearer ${authState.token}` } }
);
```

### After (Ayrshare API)

```javascript
// We manage the Token Exchange, TTL monitoring, and network retries globally.
const ayrshare = require("ayrshare")("YOUR_AYRSHARE_API_KEY");

const response = await ayrshare.post({
  post: "Hello World",
  platforms: ["facebook", "linkedin"],
  profileKeys: ["client_profile_key"] // Routes to the user, we handle the tokens
});

// Done. No Redis locks, no cron jobs, no 401 Expired Token errors.
```

For more detail, see [LinkedIn Linking](/docs/dashboard/connect-social-accounts/linkedin).

For more detail, see [LinkedIn API Error 401 (Invalid Grant)](/solutions/linkedin-api-error-401-invalid-grant-how-to-fix-token-expiration/).

For more detail, see [How to Fix Meta Error 200](/solutions/how-to-fix-meta-error-200-permissions-error-and-insufficient-scopes/).

## Meta & LinkedIn Token Expiration (401): FAQs

### How does Ayrshare handle Meta and LinkedIn token expiration?

Ayrshare tracks token TTLs for both Meta and LinkedIn on its own infrastructure and performs the exchange automatically before a token expires, so a customer's integration never has to catch a 401 in production.
### Why does a Meta access token need a Token Exchange step that LinkedIn doesn't?

Ayrshare's engineering team notes Meta issues a short-lived token valid for about an hour that must be exchanged for a 60-day long-lived token, while LinkedIn skips that step and issues a 60-day token directly.
### Can running multiple app instances cause a token refresh race condition?

Yes, and Ayrshare avoids this scenario because token refreshes happen once, centrally, on Ayrshare's infrastructure, rather than being triggered independently by multiple instances of a customer's own app.
### Do I need Redis or a similar locking mechanism if I use Ayrshare?

No. Ayrshare replaces the need for a distributed lock and CRON-based refresh worker; token exchange and TTL monitoring happen automatically on Ayrshare's side.

## Ship Social Features in Days, Not Quarters

Start your 28-day free trial, or talk with our team about pricing for thousands of profiles.

[Start free trial](https://app.ayrshare.com)
[Talk to sales](/contact/)
