{"record":{"id":"51cef207cfee450c","repo":"laurent22/joplin","slug":"notebooks-cannot-be-named-s-which-is-a-reserve","errorCode":null,"errorMessage":"Notebooks cannot be named \"%s\", which is a reserved title.","messagePattern":"Notebooks cannot be named \"(.+?)\", which is a reserved title\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/lib/models/Folder.ts","lineNumber":1118,"sourceCode":"\t\t\t}\n\t\t}\n\n\t\t// We allow folders with duplicate titles so that folders with the same title can exist under different parent folder. For example:\n\t\t//\n\t\t// PHP\n\t\t//     Code samples\n\t\t//     Doc\n\t\t// Java\n\t\t//     My project\n\t\t//     Doc\n\n\t\t// if (options.duplicateCheck === true && o.title) {\n\t\t// \tlet existingFolder = await Folder.loadByTitle(o.title);\n\t\t// \tif (existingFolder && existingFolder.id != o.id) throw new Error(_('A notebook with this title already exists: \"%s\"', o.title));\n\t\t// }\n\n\t\tif (options.reservedTitleCheck === true && o.title) {\n\t\t\tif (o.title === Folder.conflictFolderTitle()) throw new Error(_('Notebooks cannot be named \"%s\", which is a reserved title.', o.title));\n\t\t}\n\n\t\tsyncDebugLog.info('Folder Save:', o);\n\n\t\tlet savedFolder: FolderEntity = await super.save(o, options);\n\n\t\t// Ensures that any folder added to the state has all the required\n\t\t// properties, in particular \"share_id\" and \"parent_id', which are\n\t\t// required in various parts of the code.\n\t\tif (!('share_id' in savedFolder) || !('parent_id' in savedFolder) || !('deleted_time' in savedFolder)) {\n\t\t\tsavedFolder = await this.load(savedFolder.id);\n\t\t}\n\n\t\tthis.dispatch({\n\t\t\ttype: 'FOLDER_UPDATE_ONE',\n\t\t\titem: savedFolder,\n\t\t});\n","sourceCodeStart":1100,"sourceCodeEnd":1136,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/lib/models/Folder.ts#L1100-L1136","documentation":"Thrown by Folder.save when options.reservedTitleCheck is true and o.title exactly equals Folder.conflictFolderTitle(), which returns the localized string for 'Conflicts' (packages/lib/models/Folder.ts:195). That title is reserved for Joplin's built-in conflict notebook (Folder.conflictFolder / getConflictFolderId), so letting a user create one would collide with the reserved id and corrupt conflict resolution. reservedTitleCheck defaults on only when userSideValidation is true.","triggerScenarios":"Calling Folder.save(folder, { userSideValidation: true }) (which auto-enables reservedTitleCheck) — or passing reservedTitleCheck: true directly — with o.title set to the localized word for 'Conflicts' (e.g. 'Conflicts' in English, the translated term in other locales). Exact, case-sensitive equality only.","commonSituations":"A user typing 'Conflicts' as a notebook name in the UI; a rename operation hitting the reserved word; localized builds where the user typed the translated conflict title; import scripts that create notebooks from arbitrary external names without filtering reserved words.","solutions":["In the rename/create UI, block or auto-suffix titles equal to Folder.conflictFolderTitle() before calling save.","If the user genuinely wants a notebook named 'Conflicts', pick an alternate spelling or suffix (e.g. 'Conflicts (personal)') — the exact reserved string is the only blocked value.","For non-user-initiated persistence (import/sync replay), omit userSideValidation/reservedTitleCheck so the reserved check does not apply.","Compare against the localized conflictFolderTitle() (not a hard-coded English string) so the guard is correct across locales."],"exampleFix":"// before\nfolder.title = newTitle;\nawait Folder.save(folder, { userSideValidation: true });\n\n// after\nif (newTitle === Folder.conflictFolderTitle()) {\n  throw new Error(`The name \"${newTitle}\" is reserved; choose a different notebook title.`);\n}\nfolder.title = newTitle;\nawait Folder.save(folder, { userSideValidation: true });","handlingStrategy":"validation","validationCode":"// Block the reserved conflict title (locale-aware) before saving.\nfunction isReservedTitle(title: string): boolean {\n  return Boolean(title) && title === Folder.conflictFolderTitle();\n}\n\nif (isReservedTitle(folder.title)) {\n  throw new Error(`\"${folder.title}\" is a reserved notebook name.`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await Folder.save(folder, { userSideValidation: true });\n} catch (error) {\n  if (error.message.startsWith('Notebooks cannot be named')) {\n    // Prompt the user for a different name; re-render the rename dialog.\n    return showRenameError(error.message);\n  }\n  throw error;\n}","preventionTips":["Compare candidate titles against Folder.conflictFolderTitle() (the localized value) rather than a hard-coded English 'Conflicts'.","Disable the save/confirm button in the UI when the entered title equals the reserved conflict title.","Reserve the conflict title at the form-validation layer so the user never submits it, not just at the model layer.","For import/sync code that intentionally persists arbitrary titles, omit reservedTitleCheck / userSideValidation rather than patching titles."],"tags":["model","folder","validation","reserved-name","i18n"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}