{"id":"391ff647f3ea264d","repo":"redis/redis-py","slug":"himport-fieldset-must-have-at-least-one-field","errorCode":null,"errorMessage":"HIMPORT fieldset must have at least one field","messagePattern":"HIMPORT fieldset must have at least one field","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/himport.py","lineNumber":248,"sourceCode":"        can be slow, or -- for a generator that inspects this same registry -- can\n        re-enter a locked read (e.g. ``yield`` then ``registry.names()``). Running\n        it under the non-reentrant ``_lock`` would stall every registry user or\n        deadlock permanently. Field order is preserved; nothing is reordered or\n        deduplicated.\n        \"\"\"\n        # A bare single field name (str/bytes/bytearray/memoryview) is itself\n        # iterable element-by-element; that is almost certainly a caller mistake and\n        # would silently register single-character/single-byte \"fields\" (e.g.\n        # memoryview(b\"id\") -> field names 105, 100), so reject it as invalid local\n        # API usage. int/float are not iterable, so tuple() below rejects them.\n        if isinstance(fields, (str, bytes, bytearray, memoryview)):\n            raise DataError(\n                \"HIMPORT fields must be a collection of field names, \"\n                \"not a single string or binary value\"\n            )\n        field_tuple = tuple(fields)\n        if not field_tuple:\n            raise DataError(\"HIMPORT fieldset must have at least one field\")\n        return field_tuple\n\n    def _set(self, name: str, field_tuple: tuple) -> HImportFieldset:\n        # ``field_tuple`` is already validated/materialized by\n        # :meth:`_materialize_fields`; only the (cheap, non-blocking) revision bump\n        # and dict mutation run here, so ``_lock`` is never held across arbitrary\n        # caller code.\n        fieldset = HImportFieldset(\n            name=name,\n            fields=field_tuple,\n            version=self._advance(),\n        )\n        self._fieldsets[name] = fieldset\n        return fieldset\n\n    # -- mutation ---------------------------------------------------------\n\n    def prepare(self, name: str, fields: Iterable[FieldT]) -> HImportFieldset:","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/himport.py#L230-L266","documentation":"Raised as redis.exceptions.DataError by HImportRegistry._materialize_fields (redis/himport.py:248). After materializing the caller's iterable into a tuple, an empty result means the fieldset declares no fields, which is meaningless for HIMPORT PREPARE (the server needs at least one field). The registry rejects it before touching any connection or server state.","triggerScenarios":"Calling registry.prepare(name, []) or with an iterable that yields zero elements (an empty generator, a filtered list with no matches).","commonSituations":"Passing an empty list by mistake; a list comprehension that produced nothing; a config-driven field list that was not populated.","solutions":["Ensure the field collection is non-empty before calling prepare().","Validate at the source: if the field list is empty, skip the prepare or raise a clearer domain error.","Guard dynamic field generation so it always yields at least one field."],"exampleFix":"// before\nfields = [f for f in config_fields if f.active]  # could be empty\nregistry.prepare('account_data', fields)\n\n// after\nfields = [f for f in config_fields if f.active]\nif not fields:\n    raise ValueError('no active fields configured')\nregistry.prepare('account_data', fields)","handlingStrategy":"validation","validationCode":"fields = list(candidate_fields)\nif not fields:\n    raise ValueError('field collection is empty')\nregistry.prepare('account_data', fields)","typeGuard":"def is_nonempty_collection(v) -> bool:\n    try:\n        return len(list(v)) > 0\n    except TypeError:\n        return False","tryCatchPattern":null,"preventionTips":["Check the field collection is non-empty before calling prepare().","Guard dynamic/comprehension-generated field lists so they always yield at least one field.","Skip prepare() (or raise a clearer domain error) when the field list is empty."],"tags":["himport","dataerror","validation","fieldset"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}