{"record":{"id":"71e02d20d63f92bf","repo":"vercel/ai","slug":"the-streamable-value-has-been-slow-to-update-this","errorCode":null,"errorMessage":"The streamable value has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`.","messagePattern":"The streamable value has been slow to update\\. This may be a bug or a performance issue or you forgot to call `\\.done\\(\\)`\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/rsc/src/streamable-value/create-streamable-value.ts","lineNumber":153,"sourceCode":"  function assertStream(method: string) {\n    if (closed) {\n      throw new Error(method + ': Value stream is already closed.');\n    }\n    if (locked) {\n      throw new Error(\n        method + ': Value stream is locked and cannot be updated.',\n      );\n    }\n  }\n\n  let warningTimeout: NodeJS.Timeout | undefined;\n  function warnUnclosedStream() {\n    if (process.env.NODE_ENV === 'development') {\n      if (warningTimeout) {\n        clearTimeout(warningTimeout);\n      }\n      warningTimeout = setTimeout(() => {\n        console.warn(\n          'The streamable value has been slow to update. This may be a bug or a performance issue or you forgot to call `.done()`.',\n        );\n      }, HANGING_STREAM_WARNING_TIME_MS);\n    }\n  }\n  warnUnclosedStream();\n\n  function createWrapped(initialChunk?: boolean): StreamableValue<T, E> {\n    // This makes the payload much smaller if there're mutative updates before the first read.\n    let init: Partial<StreamableValue<T, E>>;\n\n    if (currentError !== undefined) {\n      init = { error: currentError };\n    } else {\n      if (currentPatchValue && !initialChunk) {\n        init = { diff: currentPatchValue };\n      } else {\n        init = { curr: currentValue };","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/rsc/src/streamable-value/create-streamable-value.ts#L135-L171","documentation":"In development mode, createStreamableValue arms a timer that fires this warning if the streamable value hasn't been updated or closed within HANGING_STREAM_WARNING_TIME_MS. It signals that a stream created on the server was never finished, likely because .done(), .update(), or .append() were not called, or the value update path stalled.","triggerScenarios":"Calling createStreamableValue() on the server and neither updating nor calling .done() within the warning window; slow async work between value creation and first update; forgetting to close the stream when an error occurs.","commonSituations":"RSC/generative-UI handlers that create a streamable value but an exception skips the .done() call; long-running server operations exceeding the hang threshold; forgotten close on early-return code paths.","solutions":["Ensure every code path calls streamableValue.done() (use try/finally).","Call .update() promptly or create the value lazily right before results are available.","Call .error(...) on failure paths instead of leaving the stream open.","Increase/ignore the warning in dev if the operation is legitimately long-running."],"exampleFix":"// before\nconst value = createStreamableValue();\nconst result = await doSlowWork();\nvalue.update(result); // may never run on throw\n// after\nconst value = createStreamableValue();\ntry {\n  value.update(await doSlowWork());\n} finally {\n  value.done();\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"const value = createStreamableValue();\ntry {\n  value.update(await work());\n} catch (e) {\n  value.error(e);\n  throw e;\n} finally {\n  value.done();\n}","preventionTips":["Always pair createStreamableValue() with done()/error() in finally","Keep stream lifetime short; create the value right before async work","Test RSC handlers with simulated failures to catch unclosed streams"],"tags":["streaming","rsc","dev-warning","resource-leak"],"backgroundTag":"stream-not-closed","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}