denoland/deno · error
serde_v8: unknown ValueType for v8::Value
Error message
serde_v8: unknown ValueType for v8::Value
What it means
serde_v8 classifies a v8::Value into a ValueType by walking a chain of type checks (Array, BigInt, ArrayBuffer, view, Object, null/undefined, and earlier branches). This panic is the exhaustive-match guard: the value passed none of the checks. With a well-formed handle from a live isolate it is unreachable; it fires only when the handle is invalid, stale, or of a v8 kind this serde_v8 version does not know.
Source
Thrown at libs/serde_v8/payload.rs:41
return Self::Bool;
} else if v.is_number() {
return Self::Number;
} else if v.is_string() {
return Self::String;
} else if v.is_array() {
return Self::Array;
} else if v.is_big_int() {
return Self::BigInt;
} else if v.is_array_buffer() {
return Self::ArrayBuffer;
} else if v.is_array_buffer_view() {
return Self::ArrayBufferView;
} else if v.is_object() {
return Self::Object;
} else if v.is_null_or_undefined() {
return Self::Null;
}
panic!("serde_v8: unknown ValueType for v8::Value")
}
}
View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Ensure every v8 handle passed to serde_v8 comes from the same live isolate and an active HandleScope
- Align deno_core, serde_v8, and the v8 crate versions in your lockfile
- In ops, take v8 values as arguments managed by deno_core instead of storing Locals yourself
- If versions are aligned and it still fires, report upstream with a reproducer - a v8 kind may be missing from the branch list
Defensive patterns
Strategy: type-guard
Type guard
use deno_core::v8;
enum ValueType { Number, Boolean, String, Symbol, Array, BigInt, ArrayBuffer, ArrayBufferView, Object, Null }
fn classify(v: v8::Local<v8::Value>) -> Option<ValueType> {
if v.is_number() { Some(ValueType::Number) }
else if v.is_boolean() { Some(ValueType::Boolean) }
else if v.is_string() { Some(ValueType::String) }
else if v.is_symbol() { Some(ValueType::Symbol) }
else if v.is_array() { Some(ValueType::Array) }
else if v.is_big_int() { Some(ValueType::BigInt) }
else if v.is_array_buffer() { Some(ValueType::ArrayBuffer) }
else if v.is_array_buffer_view() { Some(ValueType::ArrayBufferView) }
else if v.is_object() { Some(ValueType::Object) }
else if v.is_null_or_undefined() { Some(ValueType::Null) }
else { None } // would panic in serde_v8 - reject here instead
} Try / catch
let classified = std::panic::catch_unwind(|| serde_v8::classify(value));
if classified.is_err() {
// treat as an isolate/handle-lifetime bug: log, drop the handle, keep the process alive
} Prevention
- Never store v8::Local handles beyond their HandleScope; re-acquire from persistent handles inside the owning isolate
- Keep deno_core, serde_v8, and the vendored v8 crate versions in lockstep
- Treat this panic as evidence of a memory-safety-adjacent bug, not a recoverable condition
When it happens
Trigger: Passing a v8::Local obtained from a different or already-disposed isolate; using a handle after GC collected the object; running a serde_v8/deno_core build whose version predates a value kind added in the vendored v8.
Common situations: Embedder bugs that store Locals across isolate teardown; mismatched deno_core/serde_v8/v8 versions in Cargo.lock; FFI code fabricating handles.
Related errors
- {path} exists
- unable to convert
- Failed to initialize a JsRuntime: {}
- buffer must be a TypedArray or a DataView
- source must be a TypedArray or a DataView
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/507071e678239425.
Report an issue: GitHub.