{"record":{"id":"611da077e5ef54bb","repo":"Eugeny/tabby","slug":"unsupported","errorCode":null,"errorMessage":"Unsupported","messagePattern":"Unsupported","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"tabby-web/src/platform.ts","lineNumber":118,"sourceCode":"            const response = await modal.result\n            return { response }\n        } catch {\n            return { response: options.cancelId ?? 1 }\n        }\n    }\n\n    quit (): void {\n        window.close()\n    }\n\n    async startDownload (name: string, mode: number, size: number): Promise<FileDownload|null> {\n        const transfer = new HTMLFileDownload(name, mode, size)\n        this.fileTransferStarted.next(transfer)\n        return transfer\n    }\n\n    async startDownloadDirectory (_name: string, _estimatedSize?: number): Promise<DirectoryDownload|null> {\n        throw new Error('Unsupported')\n    }\n\n    startUpload (options?: FileUploadOptions): Promise<FileUpload[]> {\n        return new Promise(resolve => {\n            this.fileSelector.onchange = () => {\n                const transfers: FileUpload[] = []\n                const fileList = this.fileSelector.files!\n                // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n                for (let i = 0; i < (fileList.length ?? 0); i++) {\n                    const file = fileList[i]\n                    const transfer = new HTMLFileUpload(file)\n                    this.fileTransferStarted.next(transfer)\n                    transfers.push(transfer)\n                    if (!options?.multiple) {\n                        break\n                    }\n                }\n                resolve(transfers)","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/Eugeny/tabby/blob/14e2d60b9b6dee84a53c37f05eefeb803787de04/tabby-web/src/platform.ts#L100-L136","documentation":"Thrown by WebPlatformService.startDownloadDirectory(), the web (browser) implementation of the abstract PlatformService method. Browsers cannot stream an entire remote directory as a single download object the way Electron can, so the operation is intentionally unsupported in the web build. The base contract declares it abstract, so each platform must implement it.","triggerScenarios":"Code calls platform.startDownloadDirectory(name, size) while running under the Web platform service. The SFTP panel (sftpPanel.component.ts:257) calls this when the user chooses 'Download' on a folder in a web Tabby session.","commonSituations":"User opens the SFTP panel in the web build and tries to download a remote directory; a plugin assumes directory download is available on all platforms; the same UI is shared between Electron (supported) and Web (unsupported) builds.","solutions":["Guard the UI/action with a capability check before offering folder download on the web build.","On web, fall back to recursively downloading files individually via startDownload, or zip them server-side first.","Use the Electron/desktop build of Tabby when directory download is required.","Catch 'Unsupported' and show a user-facing message explaining the limitation."],"exampleFix":"// before\nconst transfer = await this.platform.startDownloadDirectory(folder.name, 0)\n// after\nif (this.platform instanceof WebPlatformService) {\n    this.notifications.error('Directory download is not available in the web build')\n    return\n}\nconst transfer = await this.platform.startDownloadDirectory(folder.name, 0)","handlingStrategy":"fallback","validationCode":"import { Platform } from 'tabby-core'\nfunction supportsDirDownload (platform: Platform | string): boolean {\n    return platform !== Platform.Web\n}","typeGuard":"import { WebPlatformService } from 'tabby-web'\nfunction isWebPlatform (p: unknown): p is WebPlatformService {\n    return p instanceof WebPlatformService\n}","tryCatchPattern":"try {\n    await this.platform.startDownloadDirectory(folder.name, 0)\n} catch (e) {\n    if (e.message === 'Unsupported') {\n        // web: fall back to per-file downloads\n    } else throw e\n}","preventionTips":["Check the host platform before offering folder-download UI.","On web, zip remotely or download files individually.","Keep platform-specific capability flags in a shared service."],"tags":["web","platform","sftp","download","unsupported"],"backgroundTag":null,"analyzedSha":"14e2d60b9b6dee84a53c37f05eefeb803787de04","analyzedAt":"2026-08-12T11:46:48.773Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}