Next.js use cache leak fix: keep Sume job reads out of the cache
Next.js 16.3.8 fixed use cache leaks, including Draft Mode content. A Sume job status read is live, per-workspace data, so fetch it uncached.

Should you wrap a Sume job read in use cache in a Next.js app? No. A job's status changes while you watch it, and the response belongs to one workspace, so it should be fetched fresh on the server and never stored in a shared cache. This week's Next.js security release gives a second reason to be strict: it lists two fixes for use cache, one for a root-param cache leak in nested use cache and one for a pending use cache fill that could leak Draft Mode content (Next.js September 2026 security release, read 2026-10-04).
The release shipped on September 30 as 16.3.8 for Active LTS and 15.5.27 for Maintenance LTS. Upgrade first. Then take the cache out of the path that reads job state, because that path is correct without it.
Why a cached job read is wrong even on a patched build
Sume generation is asynchronous by default. A submit returns a job id, and GET /v1/jobs/{id} reports a status until the job is terminal. The status payload carries terminal, result_ready and next_poll_after_seconds, and the docs tell clients to stop polling when terminal is true (Jobs and results). A cached processing response keeps your page showing a spinner after the job has finished.
The reverse failure is worse. A completed job read carries artifact URLs for your workspace. If a cached function is keyed by a job id and called from a request that was not authorized for that id, the cache has turned a private read into a shared one. Authorization belongs on every request, before the read.
What to cache instead
The artifact itself is a stable file once the job is terminal, served from media.sume.com. Cache that at the edge or in your own storage, keyed by the artifact id, and keep the job read dynamic. The handler below forwards a status read with no caching at either layer and passes retry-after hints through.
A Next.js route handler is dynamic when it reads the request, but the explicit no-store below makes the intent obvious to the next reader and to any proxy in front.
export async function GET(
_req: Request,
ctx: { params: Promise<{ id: string }> },
) {
const { id } = await ctx.params;
if (!/^[A-Za-z0-9_-]{6,80}$/.test(id)) {
return Response.json({ error: "bad id" }, { status: 400 });
}
const upstream = await fetch(`https://api.sume.com/v1/jobs/${id}`, {
headers: { "x-api-key": process.env.SUME_API_KEY! },
cache: "no-store",
});
const body = await upstream.text();
return new Response(body, {
status: upstream.status,
headers: {
"content-type": "application/json",
"cache-control": "private, no-store",
...(upstream.headers.get("x-sume-request-id")
? { "x-sume-request-id": upstream.headers.get("x-sume-request-id")! }
: {}),
},
});
}Checklist before you redeploy
- Search for
use cacheandunstable_cachewrappers that callapi.sume.comand remove them from job and run status paths. - Confirm every route that returns a job checks the caller's right to that job id before the upstream call.
- Forward
x-sume-request-idso support can trace a single call. - Poll from the server on the interval the status payload asks for, not from every open browser tab.
Sources
Related posts
More in Developers
- Node 24.21 MIMEType.parse: validate a Sume artifact content type
Node 24.21.0 adds a non-throwing MIMEType.parse. Use it, with a try/catch fallback for older Node, to check a Sume artifact's content_type before saving.
- Which Node versions to test the Sume SDK on: 22, 24 and 26
Node 26.10.0 is Current, 24.21.0 and 22.23.3 are LTS. A small CI matrix and smoke test for code that calls the Sume API with fetch and WebCrypto.
- Node 26.10 fs.openAsBlobSync: upload a local file with Sume uploadFile
Node 26.10 adds fs.openAsBlobSync. Open a file as a typed Blob and pass it to the Sume SDK's uploadFile to get a durable HTTPS URL for a Format input.
- Node 26.10 SQLite binds undefined as NULL: a Sume webhook job table
Node 26.10 binds undefined as NULL in node:sqlite. A Sume job-webhook handler can still be explicit with null and dedupe on job_id without a driver.
Written by Sume