laurent22/joplin · error · Error

Unsupported protocol

Error message

Unsupported protocol

What it means

Thrown when the link does not start with 'joplin://' or ':/' AND urlProtocol(link) returns a falsy value — i.e. the string has no recognizable scheme (no `scheme:` prefix). Joplin hands unknown-scheme URLs to the OS via shim.openUrl; with no scheme at all, there is nothing to open.

Source

Thrown at packages/app-mobile/commands/openItem.ts:64

					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.');
					}
				} else if (urlProtocol(link)) {
					shim.openUrl(link);
				} else {
					throw new Error('Unsupported protocol');
				}
			} catch (error) {
				const errorMessage = _('Unsupported link or message: %s.\nError: %s', link, error);
				logger.error(errorMessage);
				await shim.showErrorDialog(errorMessage);
			}
		},
	};
};

View on GitHub (pinned to 2654b33620)

Solutions

  1. Prefix the link with a scheme (https://, mailto:, etc.) before invoking openItem.
  2. Sanitize/trim the link string and re-detect its protocol.
  3. Reject empty-protocol strings earlier in the input pipeline.
  4. Catch and inform the user the link has no usable protocol.

Example fix

// before
} else {
  throw new Error('Unsupported protocol');
}

// after — explain what was expected
} else {
  throw new Error(_('Unsupported protocol in link: %s', link));
}
Defensive patterns

Strategy: validation

Validate before calling

const proto = urlProtocol(link);
if (!proto) {
  // no scheme — refuse, or prepend a default like https:// if appropriate
  return;
}
await CommandService.instance().execute('openItem', link);

Type guard

function hasProtocol(link: string): boolean {
  return !!urlProtocol(link);
}

Try / catch

try {
  await CommandService.instance().execute('openItem', link);
} catch (e) {
  if (e.message === 'Unsupported protocol') {
    // inform the user the link has no usable scheme
  } else throw e;
}

Prevention

When it happens

Trigger: link fails the joplin:///:/ check, then urlProtocol(link) is falsy (no protocol/scheme detected). The final else throws 'Unsupported protocol'.

Common situations: A bare string with no scheme (e.g. 'example.com' instead of 'https://example.com'); a relative path passed as a link; whitespace/control characters stripping the scheme; a malformed paste.

Related errors


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/9b04a4a9f9466646. Report an issue: GitHub.