Bug Report
Summary
cleo docs add <owner-id> <file> fails with E_INTERNAL: Failed to run the query '\n' (literally a newline-only SQL string). This blocks the entire attachment-based end-to-end flow for cleo docs, including list, fetch, remove, and any command that depends on attachment-store-v2 (which in turn gates publish, versions, and the full "document store for a project" vision).
The llmtxt npm dependency (llmtxt@2026.4.13) and its WASM binding are working correctly — verified via the published package's own test suite (700/700 passing) and an independent 25-doc end-to-end scale test (T848) that exercises every SDK primitive directly. The failure is isolated to cleocode's attachment-store-v2 layer.
There is an existing acknowledgement of related flakes at .cleo/agent-outputs/T-ATTACHMENT-V2-LLMTXT-BUGS/REPORT.md (CI run 24669599191, 5 tests returning 'legacy' instead of 'llmtxt'). This bug is likely the same root cause surfacing at runtime rather than just in tests.
Environment
- cleo version:
2026.4.101 (rebuilt from source at HEAD bc082e26c feat(docs): full docs SSoT surface — 6 new verbs + llmtxt v2026.4.13)
- node: v24.13.1
- llmtxt npm:
2026.4.13 (published 2026-04-21, OIDC npm provenance attested, 700/700 tests green, cargo test cargo test --all-features all green)
- llmtxt-core crate:
2026.4.13 (crates.io)
- ferrous-forge:
1.9.8 (published, ✅ All validation checks passed! on llmtxt crate)
- Shell alias for ferrous-forge has been unset in favour of
/home/keatonhoskins/.cargo/bin/ferrous-forge
- Host project being tested:
/mnt/projects/llmtxt (has .cleo/tasks.db, brain.db, conduit.db — no signaldock.db)
Reproduction
From a clean llmtxt checkout with CLEO already initialised:
cd /mnt/projects/llmtxt
mkdir -p .cleo/test-attachments
printf '# Auth Design\n\nJWT with ES256 signing.\n' > .cleo/test-attachments/auth.md
# Use any existing task ID — same failure across T814 (done), T781 (pending), T780 (epic)
cleo docs add T781 .cleo/test-attachments/auth.md 2>&1 | tail -3
Observed output
{
"level": "WARN",
"time": 1776751612631,
"subsystem": "sqlite",
"msg": "Backfilling missing name on journal entry id=null — Drizzle v1 beta requires name for applied-migration detection."
}
{
"level": "WARN",
"time": 1776751612654,
"subsystem": "sqlite",
"msg": "Backfilling missing name on journal entry id=null — Drizzle v1 beta requires name for applied-migration detection."
}
{
"success": false,
"error": {
"code": 1,
"message": "Failed to run the query '\n'",
"codeName": "E_INTERNAL"
},
"meta": {
"operation": "docs.add",
"requestId": "526b57b9-485f-4e50-beb8-30866b73301e",
"duration_ms": 49,
"timestamp": "2026-04-21T06:06:52.657Z"
}
}
Note the SQL query literal is '\n' — a bare newline string. No columns, no table. That means somewhere a query template rendered with every interpolation collapsed.
Expected output
{
"success": true,
"data": {
"attachmentId": "att_...",
"sha256": "<hash>",
"size": 42,
"backend": "llmtxt"
}
}
Downstream impact — what else this blocks
cleo docs list --task <id> returns ownerId.startsWith is not a function (which is ALSO a v2-store-path failure masquerading as a different error — the handler passes undefined through because the store couldn't index).
cleo docs fetch, remove, publish, versions, graph --owner, search --owner all resolve to 0 hits / empty / secondary errors because no attachments can be created.
Only the pure-SDK-delegating subcommands with no attachment dependency work end-to-end: search (returns hits=0 when no attachments), rank (returns empty), graph (returns nodes=0/edges=0), versions (returns 0), generate (works against the fallback generator), export (works standalone), sync, gap-check.
Root-cause hypotheses (ranked)
-
Migration state / ensureLlmtxt silent swallow. Per existing report .cleo/agent-outputs/T-ATTACHMENT-V2-LLMTXT-BUGS/REPORT.md, ensureLlmtxt() catches store.open() failures silently. If the v2 store opens partially and returns a misconfigured drizzle instance, the subsequent drizzle-orm query template can render with no params and emit '\n'. The two preceding Backfilling missing name on journal entry id=null WARNs from drizzle v1 beta strongly suggest a migration state-machine issue: the store opens, tries to backfill, but the post-backfill query path lands on an incomplete schema. The llmtxt/blob peer dep resolves, the feature-gate passes, but the attachment table isn't present or usable in the host project's .cleo/ — there is no signaldock.db in the llmtxt checkout's .cleo/ (only tasks.db, brain.db, conduit.db). v2 likely expects a separate attachments DB file that was never initialised.
-
Drizzle v1 beta template regression. The introduction of llmtxt@^2026.4.13 (which peers on drizzle-orm >=1.0.0-beta.21) may have shifted the resolved drizzle version in cleocode's workspace, and a query template that used to render INSERT INTO attachments ... now produces '\n' because of a tagged-template handling change.
-
Missing cleo init step for attachment DB. cleo init on this project returns Project already initialized. DANGER ZONE: use --force to wipe and re-init. — no opportunity to create the attachment store without a destructive reset. If v2 expects a schema that only cleo init produces, there's no idempotent migration path on an existing project.
Why we believe it is NOT an llmtxt bug
llmtxt@2026.4.13 npm tarball is clean: 700/700 tests green, smoke harness T833 (32/32) and scale test T848 (25 real docs) both pass with the exact published artefact.
packages/core/src/docs/docs-ops.ts::searchDocs, mergeDocs, buildDocsGraph, rankDocs all invoke llmtxt/similarity, llmtxt/sdk, llmtxt/graph correctly and return sane empty-state results from cleo CLI — the SDK surface is intact.
- The error message
"Failed to run the query '\n'" is raised by cleocode's own DB layer (drizzle-orm via better-sqlite3); no llmtxt code runs in the docs.add path until after the local attachment row is written.
- The llmtxt SDK has zero code paths that would interpolate an empty string into a SQL template — all SDK primitives are pure functions over Rust/WASM with no DB access.
References
- cleocode HEAD:
bc082e26c feat(docs): full docs SSoT surface — 6 new verbs + llmtxt v2026.4.13
- Related existing report:
.cleo/agent-outputs/T-ATTACHMENT-V2-LLMTXT-BUGS/REPORT.md
- llmtxt release: https://github.com/kryptobaseddev/llmtxt/releases/tag/core-v2026.4.13
- llmtxt vision scale test (bypasses cleocode attachment layer, proves SDK works):
/mnt/projects/llmtxt/.cleo/agent-outputs/T780-vision-scale-report.md
- Epic context: T780 Wave-1 + Wave-2 shipped 2026-04-21
Suggested remediation order
- Re-read
T-ATTACHMENT-V2-LLMTXT-BUGS/REPORT.md — the flaky 'legacy' vs 'llmtxt' return is likely the same root cause as the runtime empty-SQL error. Fixing the test should fix runtime.
- Add a
cleo admin init-attachments (or idempotent cleo init --attachments-only) that materialises the attachment store without requiring --force.
- Surface a proper error when
ensureLlmtxt() swallows a store.open() failure — log and return a named error code rather than silently falling through to the legacy path which then emits a cryptic empty-query error.
- Add an E2E smoke test that asserts
cleo docs add && cleo docs list returns exactly one attachment on a fresh project — this would have caught the regression before the feat(docs) commit landed.
Severity: Blocker
Area: docs
Are you using an AI agent?
Yes - AI agent filed this issue
Environment
| Component |
Version |
| CLEO |
2026.2.1 |
| Node.js |
v24.13.1 |
| OS |
linux 6.19.11-200.fc43.x86_64 x64 (x64) |
| Shell |
/bin/bash |
| gh CLI |
gh version 2.87.3 (2026-02-23) |
| Install |
/home/keatonhoskins/.npm-global/bin/cleo |
Bug Report
Summary
cleo docs add <owner-id> <file>fails withE_INTERNAL: Failed to run the query '\n'(literally a newline-only SQL string). This blocks the entire attachment-based end-to-end flow forcleo docs, includinglist,fetch,remove, and any command that depends on attachment-store-v2 (which in turn gatespublish,versions, and the full "document store for a project" vision).The llmtxt npm dependency (
llmtxt@2026.4.13) and its WASM binding are working correctly — verified via the published package's own test suite (700/700 passing) and an independent 25-doc end-to-end scale test (T848) that exercises every SDK primitive directly. The failure is isolated to cleocode'sattachment-store-v2layer.There is an existing acknowledgement of related flakes at
.cleo/agent-outputs/T-ATTACHMENT-V2-LLMTXT-BUGS/REPORT.md(CI run 24669599191, 5 tests returning'legacy'instead of'llmtxt'). This bug is likely the same root cause surfacing at runtime rather than just in tests.Environment
2026.4.101(rebuilt from source at HEADbc082e26c feat(docs): full docs SSoT surface — 6 new verbs + llmtxt v2026.4.13)2026.4.13(published 2026-04-21, OIDC npm provenance attested, 700/700 tests green, cargo testcargo test --all-featuresall green)2026.4.13(crates.io)1.9.8(published,✅ All validation checks passed!on llmtxt crate)/home/keatonhoskins/.cargo/bin/ferrous-forge/mnt/projects/llmtxt(has.cleo/tasks.db,brain.db,conduit.db— nosignaldock.db)Reproduction
From a clean llmtxt checkout with CLEO already initialised:
Observed output
{ "level": "WARN", "time": 1776751612631, "subsystem": "sqlite", "msg": "Backfilling missing name on journal entry id=null — Drizzle v1 beta requires name for applied-migration detection." } { "level": "WARN", "time": 1776751612654, "subsystem": "sqlite", "msg": "Backfilling missing name on journal entry id=null — Drizzle v1 beta requires name for applied-migration detection." } { "success": false, "error": { "code": 1, "message": "Failed to run the query '\n'", "codeName": "E_INTERNAL" }, "meta": { "operation": "docs.add", "requestId": "526b57b9-485f-4e50-beb8-30866b73301e", "duration_ms": 49, "timestamp": "2026-04-21T06:06:52.657Z" } }Note the SQL query literal is
'\n'— a bare newline string. No columns, no table. That means somewhere a query template rendered with every interpolation collapsed.Expected output
{ "success": true, "data": { "attachmentId": "att_...", "sha256": "<hash>", "size": 42, "backend": "llmtxt" } }Downstream impact — what else this blocks
cleo docs list --task <id>returnsownerId.startsWith is not a function(which is ALSO a v2-store-path failure masquerading as a different error — the handler passesundefinedthrough because the store couldn't index).cleo docs fetch,remove,publish,versions,graph --owner,search --ownerall resolve to 0 hits / empty / secondary errors because no attachments can be created.Only the pure-SDK-delegating subcommands with no attachment dependency work end-to-end:
search(returns hits=0 when no attachments),rank(returns empty),graph(returns nodes=0/edges=0),versions(returns 0),generate(works against the fallback generator),export(works standalone),sync,gap-check.Root-cause hypotheses (ranked)
Migration state / ensureLlmtxt silent swallow. Per existing report
.cleo/agent-outputs/T-ATTACHMENT-V2-LLMTXT-BUGS/REPORT.md,ensureLlmtxt()catchesstore.open()failures silently. If the v2 store opens partially and returns a misconfigured drizzle instance, the subsequent drizzle-orm query template can render with no params and emit'\n'. The two precedingBackfilling missing name on journal entry id=nullWARNs from drizzle v1 beta strongly suggest a migration state-machine issue: the store opens, tries to backfill, but the post-backfill query path lands on an incomplete schema. The llmtxt/blob peer dep resolves, the feature-gate passes, but the attachment table isn't present or usable in the host project's.cleo/— there is nosignaldock.dbin the llmtxt checkout's.cleo/(onlytasks.db,brain.db,conduit.db). v2 likely expects a separate attachments DB file that was never initialised.Drizzle v1 beta template regression. The introduction of
llmtxt@^2026.4.13(which peers ondrizzle-orm >=1.0.0-beta.21) may have shifted the resolved drizzle version in cleocode's workspace, and a query template that used to renderINSERT INTO attachments ...now produces'\n'because of a tagged-template handling change.Missing
cleo initstep for attachment DB.cleo initon this project returnsProject already initialized. DANGER ZONE: use --force to wipe and re-init.— no opportunity to create the attachment store without a destructive reset. If v2 expects a schema that onlycleo initproduces, there's no idempotent migration path on an existing project.Why we believe it is NOT an llmtxt bug
llmtxt@2026.4.13npm tarball is clean: 700/700 tests green, smoke harness T833 (32/32) and scale test T848 (25 real docs) both pass with the exact published artefact.packages/core/src/docs/docs-ops.ts::searchDocs,mergeDocs,buildDocsGraph,rankDocsall invokellmtxt/similarity,llmtxt/sdk,llmtxt/graphcorrectly and return sane empty-state results from cleo CLI — the SDK surface is intact."Failed to run the query '\n'"is raised by cleocode's own DB layer (drizzle-orm viabetter-sqlite3); no llmtxt code runs in the docs.add path until after the local attachment row is written.References
bc082e26c feat(docs): full docs SSoT surface — 6 new verbs + llmtxt v2026.4.13.cleo/agent-outputs/T-ATTACHMENT-V2-LLMTXT-BUGS/REPORT.md/mnt/projects/llmtxt/.cleo/agent-outputs/T780-vision-scale-report.mdSuggested remediation order
T-ATTACHMENT-V2-LLMTXT-BUGS/REPORT.md— the flaky'legacy'vs'llmtxt'return is likely the same root cause as the runtime empty-SQL error. Fixing the test should fix runtime.cleo admin init-attachments(or idempotentcleo init --attachments-only) that materialises the attachment store without requiring--force.ensureLlmtxt()swallows a store.open() failure — log and return a named error code rather than silently falling through to the legacy path which then emits a cryptic empty-query error.cleo docs add && cleo docs listreturns exactly one attachment on a fresh project — this would have caught the regression before thefeat(docs)commit landed.Severity: Blocker
Area: docs
Are you using an AI agent?
Yes - AI agent filed this issue
Environment