Version / build tested against
origin/main @ 66d0a22
Deployment mode
Origin — single node (local)
Engine(s) involved
Document (strict)
Summary
INSERT of an ARRAY[...] literal into a VECTOR(n) column on a document_strict collection fails. The strict coercion path drops every element, then reports the input as having 0 elements. The same literal succeeds on engine='vector' and on schemaless. A string-literal vector succeeds on document_strict. The error surfaces as XX000 (internal error) for what is a value-coercion problem.
Steps to reproduce
CREATE COLLECTION vp_strict (id TEXT PRIMARY KEY, embedding VECTOR(3))
WITH (engine = 'document_strict');
INSERT INTO vp_strict (id, embedding) VALUES ('a1', ARRAY[0.1,0.2,0.3]);
-- ERROR: serialization error (binary_tuple): bad request:
-- column 'embedding': expected VECTOR(3), got 0 elements (SQLSTATE XX000)
INSERT INTO vp_strict (id, embedding) VALUES ('a2', '[0.1,0.2,0.3]');
-- OK
Isolation across engines, same literal:
| Case |
Result |
VECTOR(3) column on document_strict, DDL |
accepted |
ARRAY[0.1,0.2,0.3] on document_strict |
got 0 elements, XX000 |
'[0.1,0.2,0.3]' string literal on document_strict |
accepted |
ARRAY[0.1,0.2,0.3] on WITH (engine = 'vector') |
accepted |
ARRAY[0.1,0.2,0.3] on schemaless |
accepted |
FLOAT column on document_strict |
accepted |
Expected behavior
ARRAY[0.1,0.2,0.3] inserts into a VECTOR(3) column on document_strict, matching every other engine. An element the coercion cannot read raises an error naming that element and its type, under a 22xxx or 42804 SQLSTATE. A client's malformed value is never XX000.
Actual behavior
extract_vector_floats at nodedb/src/data/executor/strict_format/coerce.rs:233 reads elements with a filter_map that accepts only Value::Float and Value::Integer:
arr.iter()
.filter_map(|v| match v {
Value::Float(f) => Some(*f as f32),
Value::Integer(n) => Some(*n as f32),
_ => None,
})
.collect()
Any other variant is dropped without an error. validate_and_encode_vector then compares the surviving count against the declared dimension and reports the input as having 0 elements, which misdescribes the cause: the literal carried three elements and all three were discarded.
nodedb_types::Value carries both Float and Decimal. A SQL decimal literal folding to Value::Decimal matches neither arm. That is the likely variant and is unconfirmed.
The typed Error::BadRequest raised there is flattened into Error::Serialization by the strict write wrapper, so it reaches the client as XX000.
This is not a regression. The recent plan-time column work touched coerce.rs and encode.rs only to thread a collection name through test call sites, and changed no element-reading logic.
What actually happened? (check all that are true)
Proposed severity
SEV-3 — Medium: feature wrong, but operational and a workaround exists
Reproducibility
Always — every attempt
Last known-good version / commit (if a regression)
Not a regression. Unconfirmed how far back it goes.
Environment & logs
Linux x86_64. Reproduced through the pgwire test harness against a fresh data directory. The dropped elements produce no log line — the filter_map discards them silently.
Before submitting
Version / build tested against
origin/main @ 66d0a22
Deployment mode
Origin — single node (local)
Engine(s) involved
Document (strict)
Summary
INSERTof anARRAY[...]literal into aVECTOR(n)column on adocument_strictcollection fails. The strict coercion path drops every element, then reports the input as having 0 elements. The same literal succeeds onengine='vector'and on schemaless. A string-literal vector succeeds ondocument_strict. The error surfaces asXX000(internal error) for what is a value-coercion problem.Steps to reproduce
Isolation across engines, same literal:
VECTOR(3)column ondocument_strict, DDLARRAY[0.1,0.2,0.3]ondocument_strictgot 0 elements,XX000'[0.1,0.2,0.3]'string literal ondocument_strictARRAY[0.1,0.2,0.3]onWITH (engine = 'vector')ARRAY[0.1,0.2,0.3]on schemalessFLOATcolumn ondocument_strictExpected behavior
ARRAY[0.1,0.2,0.3]inserts into aVECTOR(3)column ondocument_strict, matching every other engine. An element the coercion cannot read raises an error naming that element and its type, under a22xxxor42804SQLSTATE. A client's malformed value is neverXX000.Actual behavior
extract_vector_floatsatnodedb/src/data/executor/strict_format/coerce.rs:233reads elements with afilter_mapthat accepts onlyValue::FloatandValue::Integer:Any other variant is dropped without an error.
validate_and_encode_vectorthen compares the surviving count against the declared dimension and reports the input as having 0 elements, which misdescribes the cause: the literal carried three elements and all three were discarded.nodedb_types::Valuecarries bothFloatandDecimal. A SQL decimal literal folding toValue::Decimalmatches neither arm. That is the likely variant and is unconfirmed.The typed
Error::BadRequestraised there is flattened intoError::Serializationby the strict write wrapper, so it reaches the client asXX000.This is not a regression. The recent plan-time column work touched
coerce.rsandencode.rsonly to thread a collection name through test call sites, and changed no element-reading logic.What actually happened? (check all that are true)
engine='vector'Proposed severity
SEV-3 — Medium: feature wrong, but operational and a workaround exists
Reproducibility
Always — every attempt
Last known-good version / commit (if a regression)
Not a regression. Unconfirmed how far back it goes.
Environment & logs
Linux x86_64. Reproduced through the pgwire test harness against a fresh data directory. The dropped elements produce no log line — the
filter_mapdiscards them silently.Before submitting
mainbuild.