{"record":{"id":"9127d3ba8c11212c","repo":"python/cpython","slug":"invalid-sign-the-first-value-in-the-tuple-should","errorCode":null,"errorMessage":"Invalid sign.  The first value in the tuple should be an integer; either 0 for a positive number or 1 for a negative number.","messagePattern":"Invalid sign\\.  The first value in the tuple should be an integer; either 0 for a positive number or 1 for a negative number\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydecimal.py","lineNumber":561,"sourceCode":"            return self\n\n        # From an internal working value\n        if isinstance(value, _WorkRep):\n            self._sign = value.sign\n            self._int = str(value.int)\n            self._exp = int(value.exp)\n            self._is_special = False\n            return self\n\n        # tuple/list conversion (possibly from as_tuple())\n        if isinstance(value, (list,tuple)):\n            if len(value) != 3:\n                raise ValueError('Invalid tuple size in creation of Decimal '\n                                 'from list or tuple.  The list or tuple '\n                                 'should have exactly three elements.')\n            # process sign.  The isinstance test rejects floats\n            if not (isinstance(value[0], int) and value[0] in (0,1)):\n                raise ValueError(\"Invalid sign.  The first value in the tuple \"\n                                 \"should be an integer; either 0 for a \"\n                                 \"positive number or 1 for a negative number.\")\n            self._sign = value[0]\n            if value[2] == 'F':\n                # infinity: value[1] is ignored\n                self._int = '0'\n                self._exp = value[2]\n                self._is_special = True\n            else:\n                # process and validate the digits in value[1]\n                digits = []\n                for digit in value[1]:\n                    if isinstance(digit, int) and 0 <= digit <= 9:\n                        # skip leading zeros\n                        if digits or digit != 0:\n                            digits.append(digit)\n                    else:\n                        raise ValueError(\"The second value in the tuple must \"","sourceCodeStart":543,"sourceCodeEnd":579,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydecimal.py#L543-L579","documentation":"When constructing a Decimal from a 3-element sequence, the first element must be a Python int equal to 0 (positive) or 1 (negative). The isinstance(value[0], int) check also deliberately rejects floats like 1.0 and strings like '1'. This ValueError signals a malformed sign field in the decimal triple.","triggerScenarios":"Decimal((2, (1,), 0)); Decimal((-1, (1,), 0)); Decimal(('0', (1,), 0)); Decimal((1.0, (1,), 0)) (float, not int); Decimal((True, (1,), 0)) actually passes because bool subclasses int and True == 1.","commonSituations":"Deserializing a decimal triple from JSON where the sign became a string or was computed as -1/other values; hand-building triples from sign math that yields -1 for negatives instead of 1.","solutions":["Normalize the sign to int 0 or 1: sign = 1 if value < 0 else 0","If the sign arrived as a string from JSON/CSV, convert it explicitly: sign = int(sign_str)","Validate the triple shape before calling Decimal (see defense below)"],"exampleFix":"// before\nsign = -1 if x < 0 else 0\nd = Decimal((sign, digits, exp))  # ValueError for negatives\n\n// after\nsign = 1 if x < 0 else 0\nd = Decimal((sign, digits, exp))","handlingStrategy":"validation","validationCode":"def normalize_triple(sign, digits, exp):\n    sign = int(sign)\n    if sign not in (0, 1):\n        sign = 1 if sign else 0  # maps -1/other truthy to 1\n    return (sign, digits, exp)","typeGuard":"def valid_sign(s) -> bool:\n    return isinstance(s, int) and not isinstance(s, bool) and s in (0, 1)","tryCatchPattern":"try:\n    d = Decimal(triple)\nexcept ValueError as e:\n    if 'Invalid sign' in str(e):\n        triple = (1 if triple[0] else 0, triple[1], triple[2])\n        d = Decimal(triple)","preventionTips":["Use 0/1 sign convention everywhere; never store -1 for negative","int()-cast sign fields from JSON/CSV at the deserialization boundary","Remember bool passes the check (True==1); exclude bools if strictness matters"],"tags":["decimal","constructor","tuple","sign","validation","valueerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}