Reproduction
Using @cloudflare/shell Workspace backed by D1, create a directory shaped like an Open Agent Skill:
- SKILL.md
- scripts/setup.mjs
- references/readme.md
- assets/sample.txt
Then call workspace.rm(path, { recursive: true }) or a wrapper that delegates to it.
Observed
D1 can reject the recursive delete with:
D1_ERROR: LIKE or GLOB pattern too complex: SQLITE_ERROR
The failing path is deleteDescendants(dirPath), which deletes descendants with WHERE path LIKE ? ESCAPE ?.
Suggested fix
Use a prefix range scan instead of SQLite LIKE/ESCAPE pattern matching:
await this.sql.run(
`DELETE FROM ${T} WHERE path = ? OR (path > ? AND path < ?)`,
dirPath, `${dirPath}/`, `${dirPath}/\uFFFF`
);
The same range predicate can be used when collecting R2 keys before deletion. This avoids the LIKE complexity path and preserves prefix semantics for normalized Workspace paths.
Reproduction
Using @cloudflare/shell Workspace backed by D1, create a directory shaped like an Open Agent Skill:
Then call
workspace.rm(path, { recursive: true })or a wrapper that delegates to it.Observed
D1 can reject the recursive delete with:
D1_ERROR: LIKE or GLOB pattern too complex: SQLITE_ERRORThe failing path is
deleteDescendants(dirPath), which deletes descendants withWHERE path LIKE ? ESCAPE ?.Suggested fix
Use a prefix range scan instead of SQLite LIKE/ESCAPE pattern matching:
The same range predicate can be used when collecting R2 keys before deletion. This avoids the LIKE complexity path and preserves prefix semantics for normalized Workspace paths.