vercel/ai · error
Invalid value: this hook only accepts values created via `cr
Error message
Invalid value: this hook only accepts values created via `createStreamableValue`.
What it means
readStreamableValue only accepts objects produced by createStreamableValue; it detects the internal StreamableValue signature via isStreamableValue and throws otherwise. This prevents consuming arbitrary objects as streams and gives a clear message instead of confusing runtime failures later.
Source
Thrown at packages/rsc/src/streamable-value/read-streamable-value.tsx:38
* }
* ```
*
* And to read the value:
*
* ```js
* const streamableValue = await action()
* for await (const v of readStreamableValue(streamableValue)) {
* console.log(v)
* }
* ```
*
* This logs out 1, 2, 3 on console.
*/
export function readStreamableValue<T = unknown>(
streamableValue: StreamableValue<T>,
): AsyncIterable<T | undefined> {
if (!isStreamableValue(streamableValue)) {
throw new Error(
'Invalid value: this hook only accepts values created via `createStreamableValue`.',
);
}
return {
[Symbol.asyncIterator]() {
let row: StreamableValue<T> | Promise<StreamableValue<T>> =
streamableValue;
let value = row.curr; // the current value
let isDone = false;
let isFirstIteration = true;
return {
async next() {
// the iteration is done already, return the last value:
if (isDone) return { value, done: true };
// resolve the promise at the beginning of each iteration:View on GitHub (pinned to 69428b1f8b)
Solutions
- Pass only values returned from createStreamableValue().value
- Verify you are not passing a createStreamableUI result where a streamable value is expected
- Check for AI SDK version mismatches between server code creating the value and client code reading it
Example fix
// before const [value] = useState(42); readStreamableValue(value); // throws // after const streamable = createStreamableValue(42); readStreamableValue(streamable.value);
Defensive patterns
Strategy: type-guard
Validate before calling
import { isStreamableValue } from 'ai/rsc';
if (!isStreamableValue(maybeValue)) throw new TypeError('expected createStreamableValue().value'); Type guard
function isStreamableValueLike(v: unknown): v is StreamableValue {
return typeof v === 'object' && v !== null && 'type' in v && 'curr' in v;
} Try / catch
try {
for await (const v of readStreamableValue(input)) { /* ... */ }
} catch (e) {
if (e instanceof Error && e.message.includes('createStreamableValue')) {
console.error('Not a streamable value:', input);
return;
}
throw e;
} Prevention
- Only pass values straight from createStreamableValue
- Do not JSON round-trip StreamableValue objects
- Match AI SDK versions between producer and consumer
When it happens
Trigger: Passing a plain object, a Promise, a string, or an object created by a different library version to readStreamableValue; passing a value from createStreamableUI (UI chunk) instead of createStreamableValue; reading a deserialized value that lost the internal signature.
Common situations: Mixing value streams with UI streams; TypeScript types erased or value JSON-serialized across a boundary, dropping the marker; version mismatch between the package that created the value and the one consuming it.
Related errors
- Invalid value: this hook only accepts values created via `cr
- Chunking must be "word", "line", a RegExp, an Intl.Segmenter
- 'element streams in no-schema mode' functionality not suppor
- 'element streams in object mode' functionality not supported
- Unsupported chunk type: ${_exhaustiveCheck}
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/36d57d1a0a2d3d78.
Report an issue: GitHub.