{"record":{"id":"4fafc58c5a2244b5","repo":"xinntao/Real-ESRGAN","slug":"dataroot-gt-should-end-with-lmdb-but-receive","errorCode":null,"errorMessage":"'dataroot_gt' should end with '.lmdb', but received {self.gt_folder}","messagePattern":"'dataroot_gt' should end with '\\.lmdb', but received (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"realesrgan/data/realesrgan_dataset.py","lineNumber":47,"sourceCode":"            io_backend (dict): IO backend type and other kwarg.\n            use_hflip (bool): Use horizontal flips.\n            use_rot (bool): Use rotation (use vertical flip and transposing h and w for implementation).\n            Please see more options in the codes.\n    \"\"\"\n\n    def __init__(self, opt):\n        super(RealESRGANDataset, self).__init__()\n        self.opt = opt\n        self.file_client = None\n        self.io_backend_opt = opt['io_backend']\n        self.gt_folder = opt['dataroot_gt']\n\n        # file client (lmdb io backend)\n        if self.io_backend_opt['type'] == 'lmdb':\n            self.io_backend_opt['db_paths'] = [self.gt_folder]\n            self.io_backend_opt['client_keys'] = ['gt']\n            if not self.gt_folder.endswith('.lmdb'):\n                raise ValueError(f\"'dataroot_gt' should end with '.lmdb', but received {self.gt_folder}\")\n            with open(osp.join(self.gt_folder, 'meta_info.txt')) as fin:\n                self.paths = [line.split('.')[0] for line in fin]\n        else:\n            # disk backend with meta_info\n            # Each line in the meta_info describes the relative path to an image\n            with open(self.opt['meta_info']) as fin:\n                paths = [line.strip().split(' ')[0] for line in fin]\n                self.paths = [os.path.join(self.gt_folder, v) for v in paths]\n\n        # blur settings for the first degradation\n        self.blur_kernel_size = opt['blur_kernel_size']\n        self.kernel_list = opt['kernel_list']\n        self.kernel_prob = opt['kernel_prob']  # a list for each kernel probability\n        self.blur_sigma = opt['blur_sigma']\n        self.betag_range = opt['betag_range']  # betag used in generalized Gaussian blur kernels\n        self.betap_range = opt['betap_range']  # betap used in plateau blur kernels\n        self.sinc_prob = opt['sinc_prob']  # the probability for sinc filters\n","sourceCodeStart":29,"sourceCodeEnd":65,"githubUrl":"https://github.com/xinntao/Real-ESRGAN/blob/a4abfb2979a7bbff3f69f58f58ae324608821e27/realesrgan/data/realesrgan_dataset.py#L29-L65","documentation":"Real-ESRGAN's RealESRGANDataset validates that when the io_backend is set to 'lmdb', the gt_folder (dataroot_gt option) must point to an LMDB database directory, which by convention has a '.lmdb' suffix. The check exists because the LMDB file client uses the folder path directly as the database path, and a non-LMDB path would cause confusing downstream failures when opening the database or reading meta_info.txt. It fails fast in __init__ to surface the config mismatch immediately.","triggerScenarios":"Setting io_backend.type = 'lmdb' in the yml config while dataroot_gt points to a plain image folder (e.g. datasets/DIV2K/train/GT) or an LMDB dir without the '.lmdb' extension (e.g. datasets/DIV2K_gt). Constructing RealESRGANDataset or any train script (realesrgan/train.py) with such an opt dict triggers the ValueError during dataset init.","commonSituations":"Converting configs from disk backend to lmdb but forgetting to update dataroot_gt; renaming the LMDB folder without the .lmdb suffix; generating LMDB with create_lmdb.py which by default emits DIV2K_train.lmdb but the user points at the source image dir; copy-paste between experiments where one dataset is packed as LMDB and another is not.","solutions":["Change dataroot_gt in your yml to the actual LMDB directory ending in .lmdb (e.g. datasets/DIV2K/DIV2K_train.lmdb), which must contain data.mdb, lock.mdb, and meta_info.txt","If your data is plain images, switch io_backend.type from 'lmdb' to 'disk' in the yml so the disk+meta_info path is used","If you have no LMDB yet, generate one with scripts/data_preparation/create_lmdb.py (python create_lmdb.py --dataset DIV2K) and point dataroot_gt at the produced .lmdb folder","If the LMDB exists but was renamed, rename it back to end with .lmdb or symlink it: ln -s /path/to/db /path/to/db.lmdb"],"exampleFix":"# before (train.yml)\nio_backend:\n  type: lmdb\ndataroot_gt: datasets/DIV2K/train/GT\n\n# after\nio_backend:\n  type: lmdb\ndataroot_gt: datasets/DIV2K/DIV2K_train.lmdb","handlingStrategy":"validation","validationCode":"import os\nopt = cfg['datasets']['train']\ngt = opt['dataroot_gt']\nif opt['io_backend']['type'] == 'lmdb':\n    assert gt.endswith('.lmdb'), f'dataroot_gt must end with .lmdb, got {gt}'\n    assert os.path.isfile(os.path.join(gt, 'meta_info.txt')), 'meta_info.txt missing in LMDB dir'\n    assert os.path.isfile(os.path.join(gt, 'data.mdb')), 'data.mdb missing in LMDB dir'","typeGuard":null,"tryCatchPattern":"try:\n    dataset = RealESRGANDataset(opt)\nexcept ValueError as e:\n    raise SystemExit(f'Config error: {e}. Check dataroot_gt vs io_backend.type in your yml.') from e","preventionTips":["Always name LMDB directories with the .lmdb suffix when generating them","Keep io_backend.type and dataroot_gt in sync: lmdb <-> .lmdb folder, disk <-> image folder + meta_info","Add a startup sanity check in your training script that asserts the backend/path pairing before building the dataset"],"tags":["realesrgan","lmdb","dataset-config","validation","io-backend"],"backgroundTag":"lmdb-path-misconfigured","analyzedSha":"a4abfb2979a7bbff3f69f58f58ae324608821e27","analyzedAt":"2026-08-27T03:04:18.378Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}