nextjs - 💡(How to fix) Fix revalidateTag and revalidatePath silently fail when called from streaming Route Handler [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#86585Fetched 2026-04-08 02:10:12
View on GitHub
Comments
1
Participants
2
Timeline
6
Reactions
0
Author
Timeline (top)
labeled ×3closed ×1commented ×1locked ×1

Fix Action

Fix / Workaround

After workaround (revalidateTag called via separate HTTP request):

10:16:29.098 - calling internal endpoint
10:16:29.517 - revalidateTag called in fresh context
10:16:29.638 - cache MISS ✓

Our workaround

  • This may be related to how streaming responses handle the request lifecycle
  • The issue occurs in both development and production builds
  • We're using unstable_cache with tags, not fetch with tags
  • Workaround confirms revalidation works fine in non-streaming contexts

Code Example

// Streaming route handler with AI SDK
export async function POST(req: Request) {
  const result = streamText({
    model: google("gemini-2.5-flash"),
    tools: {
      updateData: tool({
        execute: async () => {
          // Mutation happens here
          await saveToDatabase();
          
          // This revalidation is silently ignored
          revalidateTag("my-tag", { expire: 0 });
          
          return { success: true };
        },
      }),
    },
  });
  
  return result.toDataStreamResponse();
}

---

const fetchData = unstable_cache(
  async () => fetchFromAPI(),
  ["cache-key"],
  { tags: ["my-tag"] }
);

---

10:01:08.521 - revalidateTag called
10:01:08.649 - cache HIT (should be MISS!)
10:01:39.xxx - hard reload, still cache HIT

---

10:16:29.098 - calling internal endpoint
10:16:29.517 - revalidateTag called in fresh context
10:16:29.638 - cache MISS
---

// /api/internal/invalidate/[tag]/route.ts
export async function POST(req, { params }) {
  const { tag } = await params;
  revalidateTag(tag, { expire: 0 });
  return Response.json({ ok: true });
}

// In the streaming route's tool call:
await fetch(`${baseUrl}/api/internal/invalidate/${tag}`, { method: "POST" });

---

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0

Binaries:
  Node: 22.11.0
  npm: 10.9.0
  Yarn: 1.22.22
  pnpm: 9.15.0

Relevant Packages:
  next: 16.0.0
  react: 19.0.0
  react-dom: 19.0.0

Using Vercel AI SDK (@ai-sdk/react, ai) for streaming
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/Delphia/tilt-frontend/pull/4505

To Reproduce

  1. Create a streaming Route Handler (e.g., using Vercel AI SDK's streamText)
  2. During stream execution (e.g., in a tool call), call revalidateTag() or revalidatePath()
  3. Observe that subsequent requests still hit the stale cache

Setup:

// Streaming route handler with AI SDK
export async function POST(req: Request) {
  const result = streamText({
    model: google("gemini-2.5-flash"),
    tools: {
      updateData: tool({
        execute: async () => {
          // Mutation happens here
          await saveToDatabase();
          
          // This revalidation is silently ignored
          revalidateTag("my-tag", { expire: 0 });
          
          return { success: true };
        },
      }),
    },
  });
  
  return result.toDataStreamResponse();
}

Cache setup using unstable_cache:

const fetchData = unstable_cache(
  async () => fetchFromAPI(),
  ["cache-key"],
  { tags: ["my-tag"] }
);

Current vs. Expected behavior

Current: revalidateTag() and revalidatePath() are silently ignored when called from within a streaming Route Handler. Subsequent requests continue to hit the stale cache indefinitely.

Expected: Cache should be invalidated, and subsequent requests should see fresh data.

Evidence from logs

Before fix (revalidateTag called directly in streaming context):

10:01:08.521 - revalidateTag called
10:01:08.649 - cache HIT (should be MISS!)
10:01:39.xxx - hard reload, still cache HIT

After workaround (revalidateTag called via separate HTTP request):

10:16:29.098 - calling internal endpoint
10:16:29.517 - revalidateTag called in fresh context
10:16:29.638 - cache MISS ✓

What we tested

  1. revalidateTag(tag, { expire: 0 }) - silently ignored
  2. revalidatePath(path, "layout") - also silently ignored
  3. Both are awaited - not a fire-and-forget issue

Why we couldn't test Cache Components

We have a large production application and aren't ready to migrate to use cache / cacheComponents: true as it changes semantics globally. We need unstable_cache to work reliably with revalidation.

Our workaround

Create an internal endpoint that performs revalidation in a fresh request context:

// /api/internal/invalidate/[tag]/route.ts
export async function POST(req, { params }) {
  const { tag } = await params;
  revalidateTag(tag, { expire: 0 });
  return Response.json({ ok: true });
}

// In the streaming route's tool call:
await fetch(`${baseUrl}/api/internal/invalidate/${tag}`, { method: "POST" });

This confirms the issue is specific to the streaming Route Handler context.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 25.1.0

Binaries:
  Node: 22.11.0
  npm: 10.9.0
  Yarn: 1.22.22
  pnpm: 9.15.0

Relevant Packages:
  next: 16.0.0
  react: 19.0.0
  react-dom: 19.0.0

Using Vercel AI SDK (@ai-sdk/react, ai) for streaming

Which area(s) are affected? (Select all that apply)

Data fetching (gS(S)P, getInitialProps), Middleware / No Middleware changes, Runtime

Which stage(s) are affected? (Select all that apply)

next dev (local), next build (local), Other (Deployed)

Additional context

  • This may be related to how streaming responses handle the request lifecycle
  • The issue occurs in both development and production builds
  • We're using unstable_cache with tags, not fetch with tags
  • Workaround confirms revalidation works fine in non-streaming contexts

extent analysis

TL;DR

Create an internal endpoint to perform revalidation in a fresh request context, as the revalidateTag() and revalidatePath() functions are silently ignored when called from within a streaming Route Handler.

Guidance

  • The issue is likely caused by the streaming Route Handler context, which may not properly handle the request lifecycle for cache revalidation.
  • To verify the issue, try calling revalidateTag() or revalidatePath() from a non-streaming context, such as a separate HTTP request, to see if the cache is properly invalidated.
  • As a workaround, create an internal endpoint that performs revalidation in a fresh request context, as shown in the provided example code.
  • Consider migrating to use cache / cacheComponents: true in the future, but for now, the unstable_cache workaround should suffice.

Example

// /api/internal/invalidate/[tag]/route.ts
export async function POST(req, { params }) {
  const { tag } = await params;
  revalidateTag(tag, { expire: 0 });
  return Response.json({ ok: true });
}

// In the streaming route's tool call:
await fetch(`${baseUrl}/api/internal/invalidate/${tag}`, { method:POST });

Notes

  • The issue occurs in both development and production builds, and is not specific to a particular environment or setup.
  • The workaround confirms that revalidation works fine in non-streaming contexts, which suggests that the issue is specific to the streaming Route Handler context.

Recommendation

Apply the workaround by creating an internal endpoint to perform revalidation in a fresh request context, as this has been shown to effectively invalidate the cache and resolve the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - 💡(How to fix) Fix revalidateTag and revalidatePath silently fail when called from streaming Route Handler [1 comments, 2 participants]