{"record":{"id":"ec58b9a566c5f116","repo":"hankcs/HanLP","slug":"expect-x-to-be-2-or-3-elements-but-got-repr-x","errorCode":null,"errorMessage":"Expect X to be 2 or 3 elements but got {repr(X)}","messagePattern":"Expect X to be 2 or 3 elements but got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"hanlp/transform/conll_tf.py","lineNumber":55,"sourceCode":"    def use_pos(self):\n        return self.config.get('use_pos', True)\n\n    def x_to_idx(self, x) -> Union[tf.Tensor, Tuple]:\n        form, cpos = x\n        return self.form_vocab.token_to_idx_table.lookup(form), self.cpos_vocab.token_to_idx_table.lookup(cpos)\n\n    def y_to_idx(self, y):\n        head, rel = y\n        return head, self.rel_vocab.token_to_idx_table.lookup(rel)\n\n    def X_to_inputs(self, X: Union[tf.Tensor, Tuple[tf.Tensor]]) -> Iterable:\n        if len(X) == 2:\n            form_batch, cposes_batch = X\n            mask = tf.not_equal(form_batch, 0)\n        elif len(X) == 3:\n            form_batch, cposes_batch, mask = X\n        else:\n            raise ValueError(f'Expect X to be 2 or 3 elements but got {repr(X)}')\n        sents = []\n\n        for form_sent, cposes_sent, length in zip(form_batch, cposes_batch,\n                                                  tf.math.count_nonzero(mask, axis=-1)):\n            forms = tolist(form_sent)[1:length + 1]\n            cposes = tolist(cposes_sent)[1:length + 1]\n            sents.append([(self.form_vocab.idx_to_token[f],\n                           self.cpos_vocab.idx_to_token[c]) for f, c in zip(forms, cposes)])\n\n        return sents\n\n    def lock_vocabs(self):\n        super().lock_vocabs()\n        self.puncts = tf.constant([i for s, i in self.form_vocab.token_to_idx.items()\n                                   if ispunct(s)], dtype=tf.int64)\n\n    def file_to_inputs(self, filepath: str, gold=True):\n        assert gold, 'only support gold file for now'","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/hankcs/HanLP/blob/ddb1299bddff079e447af52ec12549c50636bfa8/hanlp/transform/conll_tf.py#L37-L73","documentation":"X_to_inputs expects the feature batch X to be a 2-tuple (forms, cposes) or 3-tuple (forms, cposes, mask), matching the TF parsing model's output arrangement. Any other length triggers this ValueError.","triggerScenarios":"Calling XY_to_inputs_outputs/X_to_inputs with an X that is a list/tuple of length other than 2 or 3, e.g. feeding raw tensors, a single stacked tensor, or a 4-element tuple with extra features.","commonSituations":"Changing the model's feature layout without updating the transform; passing numpy arrays from a different pipeline; hand-crafting inputs for the TF parser.","solutions":["Pack X as exactly (form_batch, cposes_batch) or (form_batch, cposes_batch, mask).","Check the upstream component that produced X — a mismatch usually means you are feeding data from the wrong model/stage.","Verify no extra element (e.g. lemma features) was appended to X."],"exampleFix":"# before\ninputs = transform.X_to_inputs([forms, cposes, mask, lemmas])\n# after\ninputs = transform.X_to_inputs([forms, cposes, mask])","handlingStrategy":"type-guard","validationCode":"assert isinstance(X, (list, tuple)) and len(X) in (2, 3), 'X must be (forms, cposes[, mask])'","typeGuard":"def is_valid_X(X):\n    return isinstance(X, (list, tuple)) and len(X) in (2, 3) and hasattr(X[0], 'shape')","tryCatchPattern":null,"preventionTips":["Construct X right where the model outputs are unpacked, so element count matches by construction.","Pin the model/transform pair from the same HanLP version."],"tags":["tensorflow","parsing","input-shape","validation"],"backgroundTag":"invalid-input-shape","analyzedSha":"ddb1299bddff079e447af52ec12549c50636bfa8","analyzedAt":"2026-08-27T03:36:54.287Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}