{"record":{"id":"0974f495edee94db","repo":"kovidgoyal/kitty","slug":"the-file-id-ftc-file-id-already-exists","errorCode":null,"errorMessage":"The file_id {ftc.file_id} already exists","messagePattern":"The file_id (.+?) already exists","errorType":"exception","errorClass":"TransmissionError","httpStatus":null,"severity":"error","filePath":"kitty/file_transmission.py","lineNumber":619,"sourceCode":"        self.pending_files_to_transmit_signature_of: Deque[tuple[PatchFile, str]] = deque()\n        self.signature_pending_chunks: Deque[FileTransmissionCommand] = deque()\n\n    @property\n    def is_expired(self) -> bool:\n        return monotonic() - self.last_activity_at > (60 * EXPIRE_TIME)\n\n    def close(self) -> None:\n        for x in self.files.values():\n            x.close()\n        self.files = {}\n\n    def cancel(self) -> None:\n        self.close()\n\n    def start_file(self, ftc: FileTransmissionCommand) -> DestFile:\n        self.last_activity_at = monotonic()\n        if ftc.file_id in self.files:\n            raise TransmissionError(\n                msg=f'The file_id {ftc.file_id} already exists',\n                file_id=ftc.file_id,\n            )\n        self.files[ftc.file_id] = df = DestFile(ftc)\n        return df\n\n    def add_data(self, ftc: FileTransmissionCommand) -> DestFile:\n        self.last_activity_at = monotonic()\n        df = self.files.get(ftc.file_id)\n        if df is None:\n            raise TransmissionError(file_id=ftc.file_id, msg='Cannot write to a file without first starting it')\n        if df.failed:\n            return df\n        try:\n            df.write_data(self.files, ftc.data, ftc.action is Action.end_data)\n        except Exception:\n            df.failed = True\n            with suppress(Exception):","sourceCodeStart":601,"sourceCodeEnd":637,"githubUrl":"https://github.com/kovidgoyal/kitty/blob/6d5d0c440603ad9bdf6dcd599f73f6dde21acb44/kitty/file_transmission.py#L601-L637","documentation":"The receiving side tracks in-flight transfers by file_id; start_file refuses to open a file_id that is already present in self.files, raising TransmissionError('The file_id ... already exists').","triggerScenarios":"handle_receive_cmd receives two action=file commands with the same file_id before the first completes/end_data clears it — duplicated start frames or sender reusing ids in one session.","commonSituations":"Retry logic that resends the start command; senders generating ids with a weak counter that resets; concurrent transfers accidentally sharing id namespace.","solutions":["Use unique file_ids per transfer (uuid or monotonic counter per session).","Dedupe retries so the start frame is sent exactly once.","If a transfer aborted, send a cancel/finish for the stale id before reusing it."],"exampleFix":"# before\nfile_id = 'f'  # reused for every file\n# after\nimport uuid\nfile_id = str(uuid.uuid4())","handlingStrategy":"validation","validationCode":"if ftc.file_id in receiver.files:\n    receiver.cancel(ftc.file_id)  # or reject before start","typeGuard":null,"tryCatchPattern":"try:\n    receiver.start_file(ftc)\nexcept TransmissionError as e:\n    if 'already exists' in e.msg: receiver.cancel(ftc); receiver.start_file(ftc)\n    else: raise","preventionTips":["Generate file_id with uuid4 per file per session.","Cancel stale ids before reuse."],"tags":["kitty","file-transfer","duplicate-id"],"backgroundTag":"duplicate-resource-id","analyzedSha":"6d5d0c440603ad9bdf6dcd599f73f6dde21acb44","analyzedAt":"2026-08-27T14:20:20.142Z","schemaVersion":2},"datasetVersion":"2026-08-27T19:17:21.184Z"}