{"record":{"id":"9b04a4a9f9466646","repo":"laurent22/joplin","slug":"unsupported-protocol","errorCode":null,"errorMessage":"Unsupported protocol","messagePattern":"Unsupported protocol","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/app-mobile/commands/openItem.ts","lineNumber":64,"sourceCode":"\t\t\t\t\tconst parsedResourceUrl = parseResourceUrl(link);\n\t\t\t\t\tconst parsedCallbackUrl = isCallbackUrl(link) ? parseCallbackUrl(link) : null;\n\n\t\t\t\t\tif (parsedResourceUrl) {\n\t\t\t\t\t\tconst { itemId, hash } = parsedResourceUrl;\n\t\t\t\t\t\tawait openItemById(itemId, hash);\n\t\t\t\t\t} else if (parsedCallbackUrl) {\n\t\t\t\t\t\tconst id = parsedCallbackUrl.params.id;\n\t\t\t\t\t\tif (!id) {\n\t\t\t\t\t\t\tthrow new Error('Missing item ID');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tawait openItemById(id);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new Error('Unsupported link format.');\n\t\t\t\t\t}\n\t\t\t\t} else if (urlProtocol(link)) {\n\t\t\t\t\tshim.openUrl(link);\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error('Unsupported protocol');\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconst errorMessage = _('Unsupported link or message: %s.\\nError: %s', link, error);\n\t\t\t\tlogger.error(errorMessage);\n\t\t\t\tawait shim.showErrorDialog(errorMessage);\n\t\t\t}\n\t\t},\n\t};\n};\n","sourceCodeStart":46,"sourceCodeEnd":74,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-mobile/commands/openItem.ts#L46-L74","documentation":"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.","triggerScenarios":"link fails the joplin:///:/ check, then urlProtocol(link) is falsy (no protocol/scheme detected). The final else throws 'Unsupported protocol'.","commonSituations":"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.","solutions":["Prefix the link with a scheme (https://, mailto:, etc.) before invoking openItem.","Sanitize/trim the link string and re-detect its protocol.","Reject empty-protocol strings earlier in the input pipeline.","Catch and inform the user the link has no usable protocol."],"exampleFix":"// before\n} else {\n  throw new Error('Unsupported protocol');\n}\n\n// after — explain what was expected\n} else {\n  throw new Error(_('Unsupported protocol in link: %s', link));\n}","handlingStrategy":"validation","validationCode":"const proto = urlProtocol(link);\nif (!proto) {\n  // no scheme — refuse, or prepend a default like https:// if appropriate\n  return;\n}\nawait CommandService.instance().execute('openItem', link);","typeGuard":"function hasProtocol(link: string): boolean {\n  return !!urlProtocol(link);\n}","tryCatchPattern":"try {\n  await CommandService.instance().execute('openItem', link);\n} catch (e) {\n  if (e.message === 'Unsupported protocol') {\n    // inform the user the link has no usable scheme\n  } else throw e;\n}","preventionTips":["Ensure links carry a scheme (https://, mailto:, joplin://) before invoking openItem.","Trim/sanitize pasted links so leading whitespace doesn't strip the scheme.","Reject protocol-less strings early in the input pipeline."],"tags":["mobile","links","validation","url-parsing","protocol"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}