{"record":{"id":"13c2e4860de9d330","repo":"laurent22/joplin","slug":"cannot-change-encrypted-item","errorCode":null,"errorMessage":"Cannot change encrypted item","messagePattern":"Cannot change encrypted item","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/app-cli/app/base-command.ts","lineNumber":22,"sourceCode":"// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Stdout can be called with formatted strings or arbitrary values\ntype StdoutFn = (text: any)=> void;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Prompt response varies by type and tests pass sync mocks\ntype PromptFn = (message: string, options: any)=> any;\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Redux dispatch action shape varies\ntype DispatcherFn = (action: any)=> any;\n\nexport default class BaseCommand {\n\n\tprotected stdout_: StdoutFn | null = null;\n\tprotected prompt_: PromptFn | null = null;\n\tprotected dispatcher_: DispatcherFn | null = null;\n\n\tpublic usage(): string {\n\t\tthrow new Error('Usage not defined');\n\t}\n\n\tpublic encryptionCheck(item: { encryption_applied?: number } | null) {\n\t\tif (item && item.encryption_applied) throw new Error(_('Cannot change encrypted item'));\n\t}\n\n\tpublic description(): string {\n\t\tthrow new Error('Description not defined');\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Subclasses override with command-specific arg shapes; parameters are contravariant so a narrower base would break all overrides\n\tpublic async action(_args: any) {\n\t\tthrow new Error('Action not defined');\n\t}\n\n\tpublic compatibleUis() {\n\t\treturn ['cli', 'gui'];\n\t}\n\n\tpublic supportsUi(ui: string) {\n\t\treturn this.compatibleUis().indexOf(ui) >= 0;\n\t}","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-cli/app/base-command.ts#L4-L40","documentation":"BaseCommand.encryptionCheck is a guard called by mutating commands (attach, done, edit, etc.). If the supplied item has a truthy encryption_applied field — meaning the item is end-to-end encrypted on disk and has not been decrypted — it throws 'Cannot change encrypted item'. This prevents writing cleartext changes that would corrupt the encrypted blob. The message is i18n-translated.","triggerScenarios":"Trying to edit, attach to, or toggle a todo on a note while E2EE is enabled but the master key has not been supplied (or decryption is disabled), so the note is still stored encrypted.","commonSituations":"E2EE enabled on a new device before entering the master password; notes synced in encrypted form before the local client unlocked them; scripting against an encrypted profile.","solutions":["Decrypt the item first: run 'e2ee decrypt' / provide the master password so encryption_applied is cleared.","Verify status with 'e2ee status' to confirm the key is active.","Disable E2EE on the sync target if encryption is not required.","Skip the mutation and inform the user that the note must be decrypted first."],"exampleFix":"// before\n//   this.encryptionCheck(item);\n//   await modifyItem(item);\n// after\n//   if (item?.encryption_applied) {\n//     throw new Error('Decrypt the note before editing (e2ee decrypt)');\n//   }\n//   await modifyItem(item);","handlingStrategy":"type-guard","validationCode":"if (item?.encryption_applied) {\n  throw new Error('Note is encrypted; decrypt with `e2ee decrypt` before editing.');\n}","typeGuard":"const isDecrypted = (item: { encryption_applied?: number } | null): boolean =>\n  !item || !item.encryption_applied;","tryCatchPattern":null,"preventionTips":["Run 'e2ee decrypt' / supply the master password before editing on an E2EE-enabled device.","Check 'e2ee status' to confirm the key is active in scripts.","Guard every mutating command with encryptionCheck (it is inherited from BaseCommand)."],"tags":["e2ee","encryption","cli","data-integrity","i18n"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}