{"record":{"id":"4cb6358c734aa757","repo":"laurent22/joplin","slug":"unsupported-item-type-item-type","errorCode":null,"errorMessage":"Unsupported item type: ${item.type_}","messagePattern":"Unsupported item type: (.+?)","errorType":"http","errorClass":"Error","httpStatus":400,"severity":"warning","filePath":"packages/app-cli/app/app-gui.ts","lineNumber":729,"sourceCode":"\t\t\t\tconst item = await BaseItem.loadItemById(itemId);\n\t\t\t\tif (!item) throw new Error(`No item with ID ${itemId}`); // Should be nearly impossible\n\n\t\t\t\tif (item.type_ === BaseModel.TYPE_RESOURCE) {\n\t\t\t\t\tif (item.mime) response.setHeader('Content-Type', item.mime);\n\t\t\t\t\tresponse.write(await Resource.content(item));\n\t\t\t\t} else if (item.type_ === BaseModel.TYPE_NOTE) {\n\t\t\t\t\tconst html = [\n\t\t\t\t\t\t`\n\t\t\t\t\t\t<!DOCTYPE html>\n\t\t\t\t\t\t<html class=\"client-nojs\" lang=\"en\" dir=\"ltr\">\n\t\t\t\t\t\t<head><meta charset=\"UTF-8\"/></head><body>\n\t\t\t\t\t`,\n\t\t\t\t\t];\n\t\t\t\t\thtml.push(`<pre>${htmlentities(item.title)}\\n\\n${htmlentities(item.body)}</pre>`);\n\t\t\t\t\thtml.push('</body></html>');\n\t\t\t\t\tresponse.write(html.join(''));\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(`Unsupported item type: ${item.type_}`);\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t});\n\n\t\tawait this.resourceServer_.start();\n\t\tif (!this.resourceServer_.started()) return;\n\n\t\tnoteTextWidget.markdownRendererOptions = {\n\t\t\tlinkUrlRenderer: (index: number, url: string) => {\n\t\t\t\tif (!url) return url;\n\n\t\t\t\tif (resourceIdRegex.test(url)) {\n\t\t\t\t\tnoteLinks[index] = {\n\t\t\t\t\t\ttype: 'item',","sourceCodeStart":711,"sourceCodeEnd":747,"githubUrl":"https://github.com/laurent22/joplin/blob/2654b33620775080d1d59c552259d41e33dad3d2/packages/app-cli/app/app-gui.ts#L711-L747","documentation":"After the link handler loads the referenced item by id, it only knows how to render two kinds: TYPE_RESOURCE (writes the binary content with its mime Content-Type) and TYPE_NOTE (writes an HTML document with the title and body). For any other item.type_ (e.g. Folder, Tag, etc.) it throws 'Unsupported item type'. The throw is caught by ResourceServer and returned as a 400.","triggerScenarios":"An internal link points to an item whose type_ is neither a resource nor a note — for example a link to a notebook/folder (:/folderId) or a tag embedded in note markdown.","commonSituations":"A user manually constructs or pastes a link to a non-note/resource item; future item types are added to the sync model set without updating the renderer; a corrupted type_ value on a row.","solutions":["Add a branch for the additional item.type_ (e.g. render a folder title as HTML).","Avoid linking to item types the renderer does not support.","Write a fallback response and return true for unsupported types instead of throwing."],"exampleFix":"// before\n//   } else {\n//     throw new Error(`Unsupported item type: ${item.type_}`);\n//   }\n// after\n//   } else {\n//     response.statusCode = 415;\n//     response.write(`Cannot render item type: ${item.type_}`);\n//   }\n//   return true;","handlingStrategy":"type-guard","validationCode":"const RENDERABLE_TYPES = [BaseModel.TYPE_RESOURCE, BaseModel.TYPE_NOTE];\nif (!RENDERABLE_TYPES.includes(item.type_)) {\n  response.statusCode = 415;\n  response.write(`Cannot render item type: ${item.type_}`);\n  return true;\n}","typeGuard":"const isRenderableItemType = (item: { type_: number }): boolean =>\n  item.type_ === BaseModel.TYPE_RESOURCE || item.type_ === BaseModel.TYPE_NOTE;","tryCatchPattern":null,"preventionTips":["Render only resource and note links; warn the user about other link targets.","When adding a new sync item type, decide whether the resource server should render it and add a branch if so."],"tags":["resource-server","note-link","item-type","renderer"],"backgroundTag":null,"analyzedSha":"2654b33620775080d1d59c552259d41e33dad3d2","analyzedAt":"2026-08-12T14:26:46.263Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}