laurent22/joplin · error · Error

Unsupported item type for links: ${item.type_}

Error message

Unsupported item type for links: ${item.type_}

What it means

Thrown by openItemById when the loaded item's type_ is not Note, Resource, or Folder. The mobile link handler only knows how to navigate to those three types; anything else (tag, master_key, smart_filter, etc.) is not openable as a link target.

Source

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

	name: 'openItem',
};

const openItemById = async (itemId: string, hash?: string) => {
	logger.info(`Navigating to item ${itemId}`);
	const item: BaseItemEntity = await BaseItem.loadItemById(itemId);

	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;

View on GitHub (pinned to 2654b33620)

Solutions

  1. Validate item.type_ against the supported set (Note/Resource/Folder) before navigation.
  2. Regenerate the link so it targets a Note, Resource, or Folder.
  3. Catch and show which type was unsupported for easier diagnosis.
  4. Extend openItemById if a new type genuinely needs link support.

Example fix

// before
} else {
  throw new Error(`Unsupported item type for links: ${item.type_}`);
}

// after — name the type via ModelType for clarity
} else {
  throw new Error(`Unsupported item type for links: ${ModelType[item.type_] ?? item.type_}`);
}
Defensive patterns

Strategy: type-guard

Validate before calling

const OPENABLE = new Set([ModelType.Note, ModelType.Resource, ModelType.Folder]);
if (!OPENABLE.has(item.type_)) {
  // inform user this item type is not link-openable
  return;
}

Type guard

function isOpenableType(type: ModelType): boolean {
  return type === ModelType.Note || type === ModelType.Resource || type === ModelType.Folder;
}

Try / catch

try {
  await openItemById(itemId);
} catch (e) {
  if (e.message.startsWith('Unsupported item type')) {
    // show 'this kind of item cannot be opened'
  } else throw e;
}

Prevention

When it happens

Trigger: A joplin:///:/ link resolves to an item whose type_ is e.g. ModelType.Tag or ModelType.MasterKey. The if/else chain in openItemById exhausts the three supported branches and falls into the else.

Common situations: A link was hand-crafted or generated by a plugin pointing at a non-openable entity; a future/unknown item type returned by a newer sync; a corrupted type_ field; linking to an alarm or filter item.

Related errors


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