laurent22/joplin · warning · Error
has_more support not implemented
Error message
has_more support not implemented
What it means
Thrown by clearRoot() on the Joplin Server driver after deleting all listed items and clearing key values. If the initial list() returned hasMore === true, the driver has no pagination support in this debug/clear path and aborts rather than silently leaving items behind. It guards an incomplete implementation against partial cleanup.
Source
Thrown at packages/lib/file-api-driver-joplinServer.ts:307
public async releaseLock(type: LockType, clientType: LockClientType, clientId: string) {
await this.api().exec('DELETE', `api/locks/${type}_${clientType}_${clientId}`);
}
public async listLocks() {
return this.api().exec('GET', 'api/locks');
}
public async clearRoot(path: string) {
const response = await this.list(path);
for (const item of response.items) {
await this.delete(item.path);
}
await this.api().exec('POST', 'api/debug', null, { action: 'clearKeyValues' });
if (response.hasMore) throw new Error('has_more support not implemented');
}
}
View on GitHub (pinned to 2654b33620)
Solutions
- Paginate: call list() in a loop following context.nextLink until hasMore is false, deleting items each pass, before the clearKeyValues call.
- Reduce the number of items in the target below one page before clearing.
- Use the server-side clearKeyValues debug action alone if full deletion isn't required.
- Implement has_more handling in the driver's clearRoot as a proper fix.
Example fix
// before
public async clearRoot(path: string) {
const response = await this.list(path);
for (const item of response.items) await this.delete(item.path);
await this.api().exec('POST', 'api/debug', null, { action: 'clearKeyValues' });
if (response.hasMore) throw new Error('has_more support not implemented');
}
// after - drain pages first
public async clearRoot(path: string) {
let ctx: any = null;
do {
const response = await this.list(path, { context: ctx });
for (const item of response.items) await this.delete(item.path);
ctx = response.context;
} while (response.hasMore);
await this.api().exec('POST', 'api/debug', null, { action: 'clearKeyValues' });
} Defensive patterns
Strategy: validation
Validate before calling
// Don't call clearRoot on huge targets; or paginate yourself first.
const preview = await driver.list(path);
if (preview.hasMore) throw new Error('Clear root needs pagination; implement or shrink target.'); Type guard
function isHasMoreNotImplemented(e: any): boolean {
return e && typeof e.message === 'string' && e.message.includes('has_more support not implemented');
} Try / catch
try {
await driver.clearRoot(path);
} catch (e) {
if (isHasMoreNotImplemented(e)) {
// drain pages manually, then retry clearRoot
let ctx = null;
do { const r = await driver.list(path, { context: ctx }); for (const it of r.items) await driver.delete(it.path); ctx = r.context; } while (r.hasMore);
await driver.api().exec('POST', 'api/debug', null, { action: 'clearKeyValues' });
return;
}
throw e;
} Prevention
- Avoid clearRoot on production-sized accounts; reserve it for test/debug fixtures.
- Keep test fixture item counts below one list page.
- If you need full wipe on large accounts, implement pagination in the driver.
- Prefer server-side clearKeyValues when item deletion isn't required.
When it happens
Trigger: Calling clearRoot() (used by sync reset / debug wipe) on a Joplin Server target that contains more items than fit in a single list response page.
Common situations: Running a sync debug/reset on a large Joplin Server account; CI test fixtures that over-populate the root; a real account with many items where the dev intentionally wipes the target.
Related errors
- Could not access data on server "${options.path()}"
- rejectedByTarget
- isReadOnly
- Delta link missing: ${JSON.stringify(response)}
- No item with ID ${itemId}
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/ab47ce4bf44e6992.
Report an issue: GitHub.