{"record":{"id":"7afe2009c0dbc400","repo":"matplotlib/matplotlib","slug":"language-must-be-list-of-tuple-not-language-r","errorCode":null,"errorMessage":"language must be list of tuple, not {language!r}","messagePattern":"language must be list of tuple, not (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/matplotlib/text.py","lineNumber":1634,"sourceCode":"        \"\"\"\n        Set the language of the text.\n\n        Parameters\n        ----------\n        language : str or None\n            The language of the text in a format accepted by libraqm, namely `a BCP47\n            language code <https://www.w3.org/International/articles/language-tags/>`_.\n\n            If None, then defaults to :rc:`text.language`.\n        \"\"\"\n        _api.check_isinstance((Sequence, str, None), language=language)\n        language = mpl._val_or_rc(language, 'text.language')\n\n        if not cbook.is_scalar_or_string(language):\n            language = tuple(language)\n            for val in language:\n                if not isinstance(val, tuple) or len(val) != 3:\n                    raise TypeError('language must be list of tuple, not {language!r}')\n                sublang, start, end = val\n                if not isinstance(sublang, str):\n                    raise TypeError(\n                        'sub-language specification must be str, not {sublang!r}')\n                if not isinstance(start, int):\n                    raise TypeError('start location must be int, not {start!r}')\n                if not isinstance(end, int):\n                    raise TypeError('end location must be int, not {end!r}')\n\n        self._language = language\n        self.stale = True\n\n\nclass OffsetFrom:\n    \"\"\"Callable helper class for working with `Annotation`.\"\"\"\n\n    def __init__(self, artist, ref_coord, unit=\"points\"):\n        \"\"\"","sourceCodeStart":1616,"sourceCodeEnd":1652,"githubUrl":"https://github.com/matplotlib/matplotlib/blob/b379c1b69e012b142c0f496a52bcb30513802d72/lib/matplotlib/text.py#L1616-L1652","documentation":"Text.set_language() (lib/matplotlib/text.py) validates the libraqm language parameter. After resolving via mpl._val_or_rc(..., 'text.language'), a non-scalar value must be a sequence of 3-tuples (sub-language str, start int, end int) that describe byte ranges with per-range language tags. This TypeError is raised when an element of the sequence is not a tuple of length 3. Note the message is a plain string, not an f-string, so the traceback prints the literal text '{language!r}' instead of your value.","triggerScenarios":"set_language(['en-us']); set_language([('en', 0)]) (2-tuple); set_language([('en', 0, 5), 'fr']) (mixed). Scalar strings and None are accepted and never reach this check; only Sequence inputs are iterated.","commonSituations":"Using raqm-based complex-text rendering with mixed scripts and constructing the range list by zipping columns that have unequal lengths; passing a list of language tags only (missing the start/end indices); reading the spec as 'list of (lang, start, end)' but storing dicts instead of tuples.","solutions":["Pass either a single BCP47 string ('en-US') or a sequence of exactly (str, int, int) tuples, e.g. [('en', 0, 5), ('fr', 6, 11)].","If you only need one language for the whole string, use the scalar form and the range validation disappears.","Remember the printed message does not show the offending value (missing f-prefix) - inspect the argument you passed rather than the message text.","Ranges are byte offsets into the UTF-8 text - compute them with len(text[:i].encode('utf-8')), not character counts, or libraqm will mis-tag."],"exampleFix":"# before\nt.set_language(['en-US', 'fr-FR'])  # TypeError: not 3-tuples\n\n# after\nt.set_language([('en', 0, 5), ('fr', 6, 11)])","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"def valid_language(v):\n    if v is None or isinstance(v, str):\n        return True\n    try:\n        return all(\n            isinstance(t, tuple) and len(t) == 3\n            and isinstance(t[0], str) and isinstance(t[1], int) and isinstance(t[2], int)\n            for t in v)\n    except TypeError:\n        return False","tryCatchPattern":null,"preventionTips":["Use the scalar BCP47 string form unless you truly need per-range sub-languages.","Build range tuples explicitly as (lang, start, end) with int byte offsets.","Remember the error message prints literal '{language!r}' (missing f-prefix) - debug from your inputs, not the text."],"tags":["matplotlib","text","language","raqm","typeerror","argument-validation"],"backgroundTag":"invalid-parameter-type","analyzedSha":"b379c1b69e012b142c0f496a52bcb30513802d72","analyzedAt":"2026-08-21T23:31:55.468Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}