laurent22/joplin · error · Error
Link cannot be empty
Error message
Link cannot be empty
What it means
Thrown at the top of the openItem command's execute() when the link argument is falsy. The command needs a string to parse and dispatch; an empty/null/undefined link cannot be processed.
Source
Thrown at packages/app-mobile/commands/openItem.ts:42
if (!item) {
throw new Error(`Item not found: ${itemId}`);
}
if (item.type_ === ModelType.Note) {
await goToNote(itemId, hash);
} else if (item.type_ === ModelType.Resource) {
await showResource(item);
} else if (item.type_ === ModelType.Folder) {
await goToFolder(item.id);
} else {
throw new Error(`Unsupported item type for links: ${item.type_}`);
}
};
export const runtime = (): CommandRuntime => {
return {
execute: async (_context: CommandContext, link: string) => {
if (!link) throw new Error('Link cannot be empty');
try {
if (link.startsWith('joplin://') || link.startsWith(':/')) {
const parsedResourceUrl = parseResourceUrl(link);
const parsedCallbackUrl = isCallbackUrl(link) ? parseCallbackUrl(link) : null;
if (parsedResourceUrl) {
const { itemId, hash } = parsedResourceUrl;
await openItemById(itemId, hash);
} else if (parsedCallbackUrl) {
const id = parsedCallbackUrl.params.id;
if (!id) {
throw new Error('Missing item ID');
}
await openItemById(id);
} else {
throw new Error('Unsupported link format.');
}View on GitHub (pinned to 2654b33620)
Solutions
- Ensure the caller always passes a non-empty link string.
- Guard at the call site: only invoke openItem when link is truthy.
- If the empty link is from a UI element, disable that element when no link is set.
- Catch and ignore silently if an empty link is a benign no-op in your flow.
Example fix
// before
execute: async (_context, link) => {
if (!link) throw new Error('Link cannot be empty');
// after — no-op instead of throw for programmatic callers
execute: async (_context, link) => {
if (!link) {
logger.warn('openItem called with empty link; ignoring.');
return;
} Defensive patterns
Strategy: validation
Validate before calling
if (!link || typeof link !== 'string' || link.trim().length === 0) {
// do not call openItem — log and return
return;
}
await CommandService.instance().execute('openItem', link); Type guard
function isNonEmptyLink(link: unknown): link is string {
return typeof link === 'string' && link.trim().length > 0;
} Try / catch
try {
await CommandService.instance().execute('openItem', link);
} catch (e) {
if (e.message === 'Link cannot be empty') {
// caller bug — fix the call site rather than retry
} else throw e;
} Prevention
- Always validate the link is a non-empty string before invoking openItem.
- Disable UI entry points that fire openItem when no link is available.
- Treat empty links as a caller-side bug, not a user error.
When it happens
Trigger: Calling the openItem command's execute() with link = '' , null, or undefined. The `if (!link)` guard throws before any parsing.
Common situations: A programmatic caller (plugin, notification handler) invokes openItem without an argument; a note's link field is empty; a deep-link entry point fires with no URL payload.
Related errors
- Item not found: ${itemId}
- Unsupported item type for links: ${item.type_}
- Missing item ID
- Unsupported link format.
- Unsupported protocol
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/9e37200cf6d06626.
Report an issue: GitHub.