{"record":{"id":"f36ec804df39857a","repo":"nanocoai/nanoclaw","slug":"missingchanneladaptererror-channeltype-instance","errorCode":null,"errorMessage":"MissingChannelAdapterError(channelType, instance)","messagePattern":"MissingChannelAdapterError\\(channelType, instance\\)","errorType":"exception","errorClass":"MissingChannelAdapterError","httpStatus":null,"severity":"error","filePath":"src/channels/channel-registry.ts","lineNumber":112,"sourceCode":" * adapters, so single-instance behavior is unchanged. A named instance whose\n * adapter is offline gets the normal offline-adapter handling\n * (MissingChannelAdapterError → the delivery retry path) — never a\n * cross-identity send through a sibling bot of the same platform.\n */\nexport function createChannelDeliveryAdapter(): ChannelDeliveryAdapter {\n  return {\n    async deliver(\n      channelType: string,\n      platformId: string,\n      threadId: string | null,\n      kind: string,\n      content: string,\n      files?: OutboundFile[],\n      instance?: string,\n    ): Promise<string | undefined> {\n      const adapter = getChannelAdapterExact(instance ?? channelType);\n      if (!adapter) {\n        throw new MissingChannelAdapterError(channelType, instance);\n      }\n      return adapter.deliver(platformId, threadId, { kind, content: JSON.parse(content), files });\n    },\n    async setTyping(\n      channelType: string,\n      platformId: string,\n      threadId: string | null,\n      instance?: string,\n      status?: string,\n      statusKind?: 'auto' | 'agent',\n    ): Promise<void> {\n      const adapter = getChannelAdapterExact(instance ?? channelType);\n      await adapter?.setTyping?.(platformId, threadId, status, statusKind);\n    },\n  };\n}\n\n/**","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/nanocoai/nanoclaw/blob/294ef2aee85218b23ad30eda9dfe10e590b54a8c/src/channels/channel-registry.ts#L94-L130","documentation":"During the recursive walk, an entry name containing '/', '\\\\', or equal to '.'/'..' throws. readdir should never return such names, so this is a hard trust boundary — the module does not assume the filesystem API is honest.","triggerScenarios":"Practically unreachable via fs.readdirSync on normal platforms; could surface on exotic filesystems or if the walk logic is reused with an injected directory listing.","commonSituations":"Essentially defensive-only; hitting it suggests filesystem corruption or a non-standard fs layer (FUSE, patched runtime).","solutions":["Inspect the directory listing directly to find the malformed entry name","Repair or remove the corrupted directory entry","If using an unusual filesystem layer, reproduce on a standard fs to confirm"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { walkPluginDir(dir); } catch (e) { if (e instanceof Error && e.message.includes('entry name') && e.message.includes('not allowed')) { /* inspect and repair the directory listing */ } else throw e; }","preventionTips":["Treat this as a filesystem-corruption signal; scan the tree with find and repair"],"tags":["security","filesystem","hardening","path-traversal"],"backgroundTag":"malformed-filename-rejected","analyzedSha":"294ef2aee85218b23ad30eda9dfe10e590b54a8c","analyzedAt":"2026-08-28T13:59:10.357Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}