LeRobotV3Writer.finalize() infers feature declarations for info.json by sampling episode 0's
data parquet. The sample is capped at a single 256-row batch, so a column whose first non-null
value lands past row 256 falls through to the scalar branch and is declared
{"dtype": "float32", "shape": [1]}.
Concretely, with writer_config: {video: false} on a source where camera0 starts publishing at
frame 300 of episode 0, info.json declares observation.images.camera0 as float32 while the
parquet holds struct<bytes, path>. No error is raised; the dataset fails later at load time.
Suggested fix that keeps the memory bound: keep pulling batches until every unresolved column has
a non-null sample, or the file ends.
Deferred from the LeRobot v3 image-mode PR; targeted at a patch release.
LeRobotV3Writer.finalize()infers feature declarations forinfo.jsonby sampling episode 0'sdata parquet. The sample is capped at a single 256-row batch, so a column whose first non-null
value lands past row 256 falls through to the scalar branch and is declared
{"dtype": "float32", "shape": [1]}.Concretely, with
writer_config: {video: false}on a source wherecamera0starts publishing atframe 300 of episode 0,
info.jsondeclaresobservation.images.camera0asfloat32while theparquet holds
struct<bytes, path>. No error is raised; the dataset fails later at load time.Suggested fix that keeps the memory bound: keep pulling batches until every unresolved column has
a non-null sample, or the file ends.
Deferred from the LeRobot v3 image-mode PR; targeted at a patch release.