Describe the bug
Tests that exercise file-upload-into-blob-column on the Photo model error with:
Cannot assign a array value to scalar column \`fileData\` on the \`photo\` model.
(or lowercase filedata — same pattern, different DB-normalized column name).
This is not BoxLang-only — it also affects Lucee 6. 36 occurrences total across BoxLang (16) and Lucee 6 (20).
Evidence
Compat-matrix run #25837380625 (2026-05-13).
- BoxLang: 16 errors across
cockroachdb, mysql, oracle, postgres
- Lucee 6: 20 errors across
cockroachdb, h2, mysql, postgres, sqlserver
- Affected bundles:
wheels.tests.specs.model.crudSpec
wheels.tests.specs.global.internalSpec (the $hashedkey suite, which fixtures a Photo)
To Reproduce
- Run
wheels.tests.specs.global.internalSpec :: $hashedkey :: tests same output on either Lucee 6 or BoxLang against any DB except SQLite.
- The test fixture attempts to populate
Photo.fileData with binary data.
- The model coerces the value to an array somewhere along the way, then the property setter rejects it because the column is scalar (blob).
Expected behavior
Binary file upload data assigned to a fileData (blob/longblob/bytea) column is stored without coercion errors, on every engine.
Root cause hypothesis (not yet confirmed)
CFML doesn't have a portable "bytes" type. Different engines surface binary content differently:
- Lucee returns
java.nio.HeapByteBuffer or a byte[]
- Adobe returns
byte[]
- BoxLang appears to surface binary as a CFML array
Wheels' model property assignment likely calls IsArray() or a similar check on the incoming value, sees the BoxLang-flavored binary as an array, and refuses the assignment for scalar columns.
The fact that SQLite passes on both engines is interesting — likely because the SQLite adapter coerces blobs to strings or accepts arrays without complaint, so the model's check never trips.
Suggested investigation order
- Add a small reproducer that calls
FileReadBinary() against a known asset on each engine and inspects the runtime type with getMetadata(val).getName().
- If the engines surface different runtime types, either:
- Add an engine-adapter helper that normalizes to a portable bytes representation, or
- Relax the model's property-assignment type check to accept array-of-bytes when the column is binary.
- Pure test fix may also be possible if the fixture is what's producing the array shape — check
tests/_assets/... for how Photo is being constructed.
Suggested fix shape
Medium effort — needs investigation to choose between (a) engine adapter binary normalization or (b) test fixture rewrite. Either is one PR.
Additional context
Related: #2649
Describe the bug
Tests that exercise file-upload-into-blob-column on the
Photomodel error with:(or lowercase
filedata— same pattern, different DB-normalized column name).This is not BoxLang-only — it also affects Lucee 6. 36 occurrences total across BoxLang (16) and Lucee 6 (20).
Evidence
Compat-matrix run #25837380625 (2026-05-13).
cockroachdb,mysql,oracle,postgrescockroachdb,h2,mysql,postgres,sqlserverwheels.tests.specs.model.crudSpecwheels.tests.specs.global.internalSpec(the$hashedkeysuite, which fixtures a Photo)To Reproduce
wheels.tests.specs.global.internalSpec :: $hashedkey :: tests same outputon either Lucee 6 or BoxLang against any DB except SQLite.Photo.fileDatawith binary data.Expected behavior
Binary file upload data assigned to a
fileData(blob/longblob/bytea) column is stored without coercion errors, on every engine.Root cause hypothesis (not yet confirmed)
CFML doesn't have a portable "bytes" type. Different engines surface binary content differently:
java.nio.HeapByteBufferor abyte[]byte[]Wheels' model property assignment likely calls
IsArray()or a similar check on the incoming value, sees the BoxLang-flavored binary as an array, and refuses the assignment for scalar columns.The fact that SQLite passes on both engines is interesting — likely because the SQLite adapter coerces blobs to strings or accepts arrays without complaint, so the model's check never trips.
Suggested investigation order
FileReadBinary()against a known asset on each engine and inspects the runtime type withgetMetadata(val).getName().tests/_assets/...for how Photo is being constructed.Suggested fix shape
Medium effort — needs investigation to choose between (a) engine adapter binary normalization or (b) test fixture rewrite. Either is one PR.
Additional context
fileDatavsfiledata) split is just DB column-name normalization (PostgreSQL lowercases unquoted identifiers; MySQL keeps the original casing). Same bug; column-name presentation differs by adapter.Related: #2649