laurent22/joplin · error · Error
No notebook selected.
Error message
No notebook selected.
What it means
In App.loadItems, when a note pattern contains '*' it is treated as a wildcard title search scoped to a parent notebook via Note.previews(parent.id, ...). The parent is options.parent or app().currentFolder(); if neither is set the call throws 'No notebook selected.'. The message is i18n-translated.
Source
Thrown at packages/app-cli/app/app.ts:103
public async loadItems(type: FolderOrNoteType, pattern: string, options: { parent?: FolderEntity } | null = null): Promise<(FolderEntity | NoteEntity)[]> {
if (type === 'folderOrNote') {
const folders: FolderEntity[] = await this.loadItems(ModelType.Folder, pattern, options);
if (folders.length) return folders;
return await this.loadItems(ModelType.Note, pattern, options);
}
pattern = pattern ? pattern.toString() : '';
if (type === ModelType.Folder && (pattern === Folder.conflictFolderTitle() || pattern === Folder.conflictFolderId())) return [Folder.conflictFolder()];
if (!options) options = {};
const parent = options.parent ? options.parent : app().currentFolder();
const ItemClass = BaseItem.itemClass(type);
if (type === ModelType.Note && pattern.indexOf('*') >= 0) {
// Handle it as pattern
if (!parent) throw new Error(_('No notebook selected.'));
return await Note.previews(parent.id, { titlePattern: pattern });
} else {
// Single item
let item = null;
if (type === ModelType.Note) {
if (!parent) throw new Error(_('No notebook has been specified.'));
item = await (ItemClass as typeof Note).loadFolderNoteByField(parent.id, 'title', pattern);
} else {
item = await ItemClass.loadByTitle(pattern);
}
if (item) return [item];
item = await ItemClass.load(pattern); // Load by id
if (item) return [item];
if (pattern.length >= 2) {
return await ItemClass.loadByPartialId(pattern);
}View on GitHub (pinned to 2654b33620)
Solutions
- Select a notebook first: 'use <notebook>'.
- Pass options.parent explicitly when calling loadItems from code.
- Create a notebook if none exist: 'mkbook <name>'.
Example fix
// before // const notes = await app().loadItems(ModelType.Note, '*todo*'); // throws 'No notebook selected.' // after // await app().switchCurrentFolder(folderId); // or 'use <notebook>' in CLI // const notes = await app().loadItems(ModelType.Note, '*todo*');
Defensive patterns
Strategy: validation
Validate before calling
const parent = options?.parent ?? app().currentFolder();
if (pattern.includes('*') && !parent) {
throw new Error('Select a notebook before using a wildcard note search.');
} Try / catch
try {
await app().loadItems(ModelType.Note, pattern);
} catch (e) {
if (/No notebook selected/.test(e.message)) {
await app().switchCurrentFolder(defaultFolderId);
}
} Prevention
- Always run 'use <notebook>' (or set options.parent) before wildcard note searches.
- In scripts, pass options.parent explicitly rather than relying on GUI state.
When it happens
Trigger: Running a wildcard note search (e.g. 'ls *' or 'cat *note*') before any notebook is selected, with no options.parent supplied programmatically.
Common situations: First run of a session with no notebook chosen; all notebooks deleted; a script that calls loadItems with a wildcard but does not pass options.parent.
Related errors
- No notebook has been specified.
- Cannot find "%s".
- More than one item match "%s". Please narrow down your query
- Cannot find "%s".
- The command "%s" is only available in GUI mode
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/9c8e7d7c10f2e83b.
Report an issue: GitHub.