{"record":{"id":"9f03fd1c9120783d","repo":"subframe7536/maple-font","slug":"invalid-class-list-must-ends-with-var-hexlett","errorCode":null,"errorMessage":"Invalid class_list, must ends with [@Var, @HexLetter]","messagePattern":"Invalid class_list, must ends with \\[@Var, @HexLetter\\]","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"source/py/feature/__init__.py","lineNumber":83,"sourceCode":"        is_italic (bool): Whether to generate italic features\n        is_cn (bool): Whether to include Chinese-specific features\n        is_normal (bool): Whether to generate normal preset\n        is_calt (bool): Whether to enable calt\n        variable_enabled_feature_list (list[str]): List of features that\n            be enabled in variable format\n        infinite (bool): Whether to add infinite arrow ligatures\n    \"\"\"\n    print(\n        f\"Generating feature string with italic={is_italic}, cn={is_cn}, normal={is_normal}, calt={is_calt}, variable={bool(variable_enabled_feature_list)}, infinite={enable_infinite}, tag={enable_tag}\"\n    )\n    infinite_helper.set(enable_infinite)\n\n    class_list = class_list_italic if is_italic else class_list_regular\n    cv_list = cv_list_italic(True) if is_italic else cv_list_regular(True)\n    ss_list = ss_list_italic(True) if is_italic else ss_list_regular(True)\n\n    if class_list[-2].name != \"Var\" or class_list[-1].name != \"HexLetter\":\n        raise TypeError(\"Invalid class_list, must ends with [@Var, @HexLetter]\")\n\n    calt_feat = get_calt(\n        cls_var=class_list[-2],\n        cls_hex_letter=class_list[-1],\n        is_italic=is_italic,\n        is_normal=is_normal,\n        enable_tag=enable_tag,\n        remove_italic_calt=remove_italic_calt,\n    )\n\n    # clear calt for no ligature\n    if not is_calt:\n        calt_feat.content = []\n\n    cv_ss_list = deepcopy(cv_list + (cv_list_cn if is_cn else []) + ss_list)\n\n    # for variable font, freeze feature by moving it to `calt`\n    if variable_enabled_feature_list:","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/subframe7536/maple-font/blob/c08fda97fef73d68c1755219852150770f6e6578/source/py/feature/__init__.py#L65-L101","documentation":"generate_fea_string() assembles the font's FEA (feature file) string and relies on the caller-provided class_list ending with exactly the @Var and @HexLetter classes; these two classes are consumed as cls_var and cls_hex_letter for the calt contextual rules. If either trailing class is missing or in the wrong order, the generated substitutions would reference undefined glyph classes, so the library raises TypeError early. It is a precondition on the ordered class list structure, not on individual class contents.","triggerScenarios":"Calling generate_fea_string(class_list=...) where class_list[-2].name != 'Var' or class_list[-1].name != 'HexLetter' — e.g. passing a list built without those classes, in a different order, or with custom class lists missing them.","commonSituations":"Building a custom class_list for a custom font variant and forgetting to append cls_var and cls_hex_letter; reordering classes; copying an older class_list from a version before Var/HexLetter classes were introduced.","solutions":["Append the Var and HexLetter classes to the end of your class_list: class_list = class_list + [cls_var, cls_hex_letter].","Ensure the order is [... , @Var, @HexLetter] — Var second-to-last, HexLetter last.","Prefer using the library's class_list_italic or class_list_regular builders (or copy/extend them) instead of hand-assembling the list.","Verify class names with [c.name for c in class_list[-2:]] == ['Var', 'HexLetter'] before calling."],"exampleFix":"// before\nclass_list = my_custom_classes\ngenerate_fea_string(class_list, ...)\n// after\nclass_list = my_custom_classes + [cls_var, cls_hex_letter]\nassert class_list[-2].name == 'Var' and class_list[-1].name == 'HexLetter'\ngenerate_fea_string(class_list, ...)","handlingStrategy":"validation","validationCode":"def validate_class_list(class_list):\n    if len(class_list) < 2 or class_list[-2].name != 'Var' or class_list[-1].name != 'HexLetter':\n        raise ValueError('class_list must end with [@Var, @HexLetter]')\n\nvalidate_class_list(class_list)\ngenerate_fea_string(class_list, ...)","typeGuard":"def ends_with_var_hexletter(class_list) -> bool:\n    return len(class_list) >= 2 and class_list[-2].name == 'Var' and class_list[-1].name == 'HexLetter'","tryCatchPattern":"try:\n    fea = generate_fea_string(class_list, is_italic=is_italic)\nexcept TypeError as e:\n    if 'must ends with' in str(e):\n        class_list = class_list + [cls_var, cls_hex_letter]\n        fea = generate_fea_string(class_list, is_italic=is_italic)\n    else:\n        raise","preventionTips":["Always build class_list by extending class_list_regular/class_list_italic rather than from scratch.","Add an assert on class_list[-2:] names before every generate_fea_string call.","Keep Var and HexLetter as the final two appends in any custom list builder."],"tags":["python","typeerror","font-features","invalid-argument","fea-generation"],"backgroundTag":"invalid-class-list-order","analyzedSha":"c08fda97fef73d68c1755219852150770f6e6578","analyzedAt":"2026-08-28T22:07:29.503Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}