{"record":{"id":"cc93665eba2ba8c3","repo":"langflow-ai/langflow","slug":"extension-not-found-for-file-file-name","errorCode":null,"errorMessage":"Extension not found for file {file_name}","messagePattern":"Extension not found for file (.+?)","errorType":"http","errorClass":"HTTPException","httpStatus":500,"severity":"error","filePath":"src/backend/base/langflow/api/v1/files.py","lineNumber":136,"sourceCode":"        folder = str(flow.id)\n        await storage_service.save_file(flow_id=folder, file_name=full_file_name, data=file_content)\n        return UploadFileResponse(flow_id=str(flow.id), file_path=f\"{folder}/{full_file_name}\")\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=str(e)) from e\n\n\n@router.get(\"/download/{flow_id}/{file_name}\")\nasync def download_file(\n    file_name: ValidatedFileName,\n    flow: Annotated[Flow, Depends(get_flow)],\n    storage_service: Annotated[StorageService, Depends(get_storage_service)],\n):\n    # Authorization handled by get_flow dependency\n    flow_id_str = str(flow.id)\n    extension = file_name.split(\".\")[-1]\n\n    if not extension:\n        raise HTTPException(status_code=500, detail=f\"Extension not found for file {file_name}\")\n    try:\n        content_type = build_content_type_from_extension(extension)\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=str(e)) from e\n\n    if not content_type:\n        raise HTTPException(status_code=500, detail=f\"Content type not found for extension {extension}\")\n\n    try:\n        file_content = await storage_service.get_file(flow_id=flow_id_str, file_name=file_name)\n        headers = {\n            \"Content-Disposition\": build_content_disposition(file_name),\n            \"Content-Type\": \"application/octet-stream\",\n            \"Content-Length\": str(len(file_content)),\n        }\n        return StreamingResponse(BytesIO(file_content), media_type=content_type, headers=headers)\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=str(e)) from e","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/langflow-ai/langflow/blob/976ec789d2886a86de109c044d089d68e96c9a35/src/backend/base/langflow/api/v1/files.py#L118-L154","documentation":"HTTP 500 from GET /files/download/{flow_id}/{file_name} when the file_name has no extension — i.e. file_name.split('.')[-1] equals the whole name because there is no dot. The router param is a ValidatedFileName, so in practice this only fires if the validator permits extensionless names; the guard is a last-resort check because content-type resolution is impossible without an extension.","triggerScenarios":"GET /files/download/{flow_id}/README (no dot in name); filenames ending in a dot where split yields an empty-ish segment; URLs where the filename got truncated before the extension.","commonSituations":"Hand-constructed download URLs; files saved without extensions by external tooling; URL-encoding issues stripping the extension.","solutions":["Request the file by its exact stored name including extension (the upload response's file_path contains it)","Ensure uploaded files always carry an extension; add one at upload time if the original lacks it","List the flow's files to recover the exact file_name before constructing the download URL"],"exampleFix":"# before\nGET /api/v1/files/download/{flow_id}/data\n\n# after\nGET /api/v1/files/download/{flow_id}/2024-01-01_00-00-00_data.csv","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\ndef has_extension(file_name: str) -> bool:\n    return bool(Path(file_name).suffix)","typeGuard":"def is_downloadable_name(file_name: str) -> bool:\n    name = file_name.strip()\n    return \".\" in name and name.rsplit(\".\", 1)[1].isalnum()","tryCatchPattern":"try:\n    client.get(f\"/files/download/{flow_id}/{file_name}\").raise_for_status()\nexcept HTTPError as e:\n    if \"Extension not found\" in e.response.text:\n        file_name = lookup_stored_name(flow_id, file_name)  # find real stored name\n        client.get(f\"/files/download/{flow_id}/{file_name}\").raise_for_status()","preventionTips":["Build download URLs only from the file_path returned at upload","Require an extension when storing files"],"tags":["files","download","filename","http-500"],"backgroundTag":null,"analyzedSha":"976ec789d2886a86de109c044d089d68e96c9a35","analyzedAt":"2026-08-14T18:23:12.227Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}