{"record":{"id":"0067ebf5ce6a1c80","repo":"laurent22/joplin","slug":"no-notes-selected-for-pdf-export","errorCode":null,"errorMessage":"No notes selected for pdf export","messagePattern":"No notes selected for pdf export","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/app-desktop/gui/WindowCommandsAndDialogs/commands/exportPdf.ts","lineNumber":20,"sourceCode":"import shim from '@joplin/lib/shim';\nimport InteropServiceHelper from '../../../InteropServiceHelper';\nimport { _ } from '@joplin/lib/locale';\nimport Note from '@joplin/lib/models/Note';\nimport bridge from '../../../services/bridge';\nimport { WindowControl } from '../utils/useWindowControl';\n\nexport const declaration: CommandDeclaration = {\n\tname: 'exportPdf',\n\tlabel: () => `PDF - ${_('PDF File')}`,\n};\n\nexport const runtime = (comp: WindowControl): CommandRuntime => {\n\treturn {\n\t\texecute: async (context: CommandContext, noteIds: string[] = null) => {\n\t\t\ttry {\n\t\t\t\tnoteIds = noteIds || context.state.selectedNoteIds;\n\n\t\t\t\tif (!noteIds.length) throw new Error('No notes selected for pdf export');\n\n\t\t\t\tlet path = null;\n\t\t\t\tif (noteIds.length === 1) {\n\t\t\t\t\tpath = await bridge().showSaveDialog({\n\t\t\t\t\t\tfilters: [{ name: _('PDF File'), extensions: ['pdf'] }],\n\t\t\t\t\t\tdefaultPath: await InteropServiceHelper.defaultFilename(noteIds[0], 'pdf'),\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tpath = await bridge().showOpenDialog({\n\t\t\t\t\t\tproperties: ['openDirectory', 'createDirectory'],\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tif (Array.isArray(path)) {\n\t\t\t\t\tif (path.length > 1) {\n\t\t\t\t\t\tthrow new Error('Only one output directory can be selected');\n\t\t\t\t\t}\n","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-desktop/gui/WindowCommandsAndDialogs/commands/exportPdf.ts#L2-L38","documentation":"Thrown by the exportPdf command when noteIds resolves to an empty array. The command reads selectedNoteIds from context state (or an explicit argument) and requires at least one note to render to PDF.","triggerScenarios":"Executing exportPdf when context.state.selectedNoteIds is empty AND no noteIds argument was passed, or when an explicit empty array is passed. The guard `if (!noteIds.length)` fires immediately.","commonSituations":"The command is invoked via keyboard shortcut/menu with no note selected in the list; a plugin calls execute() without arguments while the user has deselected all notes; the note list failed to populate a selection.","solutions":["Select at least one note in the note list before triggering PDF export.","If invoking programmatically, pass an explicit non-empty noteIds array.","Gate the UI action behind a 'someNotesSelected' enabled condition so the command cannot fire with no selection.","Check context.state.selectedNoteIds.length before calling execute()."],"exampleFix":"// before\nnoteIds = noteIds || context.state.selectedNoteIds;\nif (!noteIds.length) throw new Error('No notes selected for pdf export');\n\n// after — disabled-condition style guard at the call site\nif (!noteIds || noteIds.length === 0) {\n  throw new Error('No notes selected for pdf export. Select at least one note and retry.');\n}","handlingStrategy":"validation","validationCode":"const ids = noteIds || context.state.selectedNoteIds;\nif (!ids || ids.length === 0) {\n  // prompt user to select a note, or abort\n  return;\n}\nawait CommandService.instance().execute('exportPdf', ids);","typeGuard":"function hasNotesToExport(ids: string[] | null | undefined): ids is string[] {\n  return Array.isArray(ids) && ids.length > 0;\n}","tryCatchPattern":"try {\n  await CommandService.instance().execute('exportPdf', noteIds);\n} catch (e) {\n  if (e.message === 'No notes selected for pdf export') {\n    // inform user to select at least one note\n  } else throw e;\n}","preventionTips":["Gate the exportPdf action behind a 'someNotesSelected' enabled condition.","When invoking programmatically, always pass an explicit non-empty noteIds array.","Confirm a note is selected in the list before showing the export menu item."],"tags":["desktop","export","pdf","validation","selection"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}