{"record":{"id":"466b32ecbe72f528","repo":"laurent22/joplin","slug":"cannot-find-s-466b32","errorCode":null,"errorMessage":"Cannot find: \"%s\"","messagePattern":"Cannot find: \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/app-cli/app/command-mkbook.ts","lineNumber":28,"sourceCode":"\t\treturn 'mkbook <new-notebook>';\n\t}\n\n\tpublic description() {\n\t\treturn _('Creates a new notebook.');\n\t}\n\n\tpublic options() {\n\t\treturn [\n\t\t\t['-p, --parent <parent-notebook>', _('Create a new notebook under a parent notebook.')],\n\t\t];\n\t}\n\n\t// validDestinationFolder check for presents and ambiguous folders\n\tpublic async validDestinationFolder(targetFolder: string) {\n\n\t\tconst destinationFolder = await app().loadItem(ModelType.Folder, targetFolder);\n\t\tif (!destinationFolder) {\n\t\t\tthrow new Error(_('Cannot find: \"%s\"', targetFolder));\n\t\t}\n\n\t\tconst destinationDups = await Folder.search({ titlePattern: targetFolder, limit: 2 });\n\t\tif (destinationDups.length > 1) {\n\t\t\tthrow new Error(_('Ambiguous notebook \"%s\". Please use short notebook id instead - press \"ti\" to see the short notebook id', targetFolder));\n\t\t}\n\n\t\treturn destinationFolder;\n\t}\n\n\tpublic async saveAndSwitchFolder(newFolder: FolderEntity) {\n\n\t\tconst folder = await Folder.save(newFolder, { userSideValidation: true });\n\t\tapp().switchCurrentFolder(folder);\n\n\t}\n\n\tpublic async action(args: { 'new-notebook': string; options: { parent?: string } }) {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-cli/app/command-mkbook.ts#L10-L46","documentation":"Thrown by `mkbook -p <parent> <new>` via `validDestinationFolder` when `app().loadItem(ModelType.Folder, targetFolder)` returns null. Note the message uses a colon (\"Cannot find: \\\"%s\\\"\") unlike the rest of the codebase. The method is also used by other notebook-targeting flows that need to validate a parent.","triggerScenarios":"`mkbook -p NonExistent NewBook`; typo in parent name; parent was deleted; partial id <2 chars.","commonSituations":"Creating a sub-notebook under a parent whose title was mistyped; parent notebook renamed between script write and run.","solutions":["List notebooks with `joplin ls /` and copy the exact parent title or id","Use the short notebook id (toggle ids with `ti`)","Drop `-p` to create a top-level notebook instead"],"exampleFix":"// before\njoplin mkbook -p Work Projcts \"Q3 Report\"   // typo, throws\n\n// after\njoplin ls /\n# parent title is \"Projects\"\njoplin mkbook -p Projects \"Q3 Report\"\n# or by short id:\njoplin mkbook -p 7f3a \"Q3 Report\"","handlingStrategy":"validation","validationCode":"import app from './app';\nimport { ModelType } from '@joplin/lib/BaseModel';\n\nasync function resolveParentFor(parentRef: string) {\n  const folder = await app().loadItem(ModelType.Folder, parentRef);\n  if (!folder) throw new Error(`Cannot find parent notebook \"${parentRef}\". Verify with \\`ls /\\`.`);\n  return folder;\n}","typeGuard":"const isFolderRef = (f: any): f is { id: string; title: string } =>\n  !!f && typeof f.id === 'string';","tryCatchPattern":null,"preventionTips":["Use notebook ids (short or full) instead of titles for `-p`","List parents with `ls /` before scripted `mkbook -p`","Remember this message uses a colon (\"Cannot find:\") — distinct from sibling errors"],"tags":["cli","mkbook","notebook-lookup","validation"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}