{"record":{"id":"73577a383b8f4210","repo":"microsoft/qlib","slug":"fields-cannot-be-empty","errorCode":null,"errorMessage":"fields cannot be empty","messagePattern":"fields cannot be empty","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/data/data.py","lineNumber":538,"sourceCode":"                instruments_d = Inst.list_instruments(instruments=instruments, freq=freq, as_list=False)\n            else:\n                # dict of instruments and timestamp\n                instruments_d = instruments\n        elif isinstance(instruments, (list, tuple, pd.Index, np.ndarray)):\n            # list or tuple of a group of instruments\n            instruments_d = list(instruments)\n        else:\n            raise ValueError(\"Unsupported input type for param `instrument`\")\n        return instruments_d\n\n    @staticmethod\n    def get_column_names(fields):\n        \"\"\"\n        Get column names from input fields\n\n        \"\"\"\n        if len(fields) == 0:\n            raise ValueError(\"fields cannot be empty\")\n        column_names = [str(f) for f in fields]\n        return column_names\n\n    @staticmethod\n    def parse_fields(fields):\n        # parse and check the input fields\n        return [ExpressionD.get_expression_instance(f) for f in fields]\n\n    @staticmethod\n    def dataset_processor(instruments_d, column_names, start_time, end_time, freq, inst_processors=[]):\n        \"\"\"\n        Load and process the data, return the data set.\n        - default using multi-kernel method.\n\n        \"\"\"\n        normalize_column_names = normalize_cache_fields(column_names)\n        # One process for one task, so that the memory will be freed quicker.\n        workers = max(min(C.get_kernels(freq), len(instruments_d)), 1)","sourceCodeStart":520,"sourceCodeEnd":556,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/data/data.py#L520-L556","documentation":"`Inst.get_column_names` requires at least one field. `D.features(...)` and the static data loaders build column names from the `fields` argument; an empty list means no data could ever be requested, so a ValueError is raised immediately.","triggerScenarios":"Calling `D.features(instruments, fields=[])`, or building a DatasetH/DataHandler whose `data_loader` config has `fields: []`.","commonSituations":"Configs where fields are generated dynamically (e.g. alpha158 factors list comes back empty after a bug, or a YAML list is left as a placeholder). Also after renaming, when a fields-building helper returns [].","solutions":["Pass at least one valid expression, e.g. `fields=['$close']`.","Debug why your field list is empty: print len(fields) before the call.","If fields are generated, add an early assert/guard in your config code."],"exampleFix":"# before\ndf = D.features(insts, fields=[], start_time='2020-01-01', end_time='2020-12-31')\n\n# after\ndf = D.features(insts, fields=['$close', '$volume'], start_time='2020-01-01', end_time='2020-12-31')","handlingStrategy":"validation","validationCode":"assert isinstance(fields, (list, tuple)) and len(fields) > 0, 'fields must be a non-empty list of expressions'","typeGuard":"def has_fields(fields) -> bool:\n    return bool(fields) and all(isinstance(f, str) for f in fields)","tryCatchPattern":null,"preventionTips":["Guard dynamically generated field lists with a len() check.","Keep placeholder field lists in configs out of production."],"tags":["fields","validation","config"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}