{"record":{"id":"51477afad8ef470f","repo":"subframe7536/maple-font","slug":"invalid-item-to-flatten-item","errorCode":null,"errorMessage":"Invalid item to flatten: {item}","messagePattern":"Invalid item to flatten: (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"source/py/feature/ast.py","lineNumber":559,"sourceCode":"        yield data\n\n\ndef flatten_to_lines(\n    data: Line | Clazz | Lookup | Feature | list | tuple,\n) -> list[Line]:\n    result = []\n\n    for item in recursive_iterate(data):\n        if not item:\n            continue\n        elif isinstance(item, Clazz):\n            result.append(item.state())\n        elif isinstance(item, Line):\n            result.append(item)\n        elif isinstance(item, (Lookup, Feature)):\n            result.extend(item.state())\n        else:\n            raise TypeError(f\"Invalid item to flatten: {item}\")\n\n    return result\n\n\nEMPTY_FEAT_CONTENT = [Line(\"# Placeholder\"), subst(None, \"EMquad\", None, \"space\")]\n\n\ndef clone_empty(feature: FeatureWithDocs, desc_prefix: str = \"\"):\n    if isinstance(feature, CharacterVariant):\n        return CharacterVariant(\n            id=feature.id,\n            desc=desc_prefix + EMPTY_FEAT_SYMBOL + feature.desc,\n            content=EMPTY_FEAT_CONTENT,\n            version=feature.version,\n            example=feature.example,\n        )\n    if isinstance(feature, StylisticSet):\n        return StylisticSet(","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/subframe7536/maple-font/blob/c08fda97fef73d68c1755219852150770f6e6578/source/py/feature/ast.py#L541-L577","documentation":"flatten_to_lines() normalizes feature content into a flat list of Line objects; it accepts items that expose .state(), Line instances, and Lookup/Feature objects (expanded via their .state()). Any other object type in the content list is unsupported and raises TypeError 'Invalid item to flatten'. It guards the internal content model of features, lookups, and lines.","triggerScenarios":"Passing a feature content list containing raw strings, dicts, integers, or arbitrary objects to anything that flows through flatten_to_lines — Feature/FeatureWithDocs construction content, Lookup, or calls to create/state/cls_states.","commonSituations":"Hand-writing content as plain strings like '# comment' instead of Line('# comment'); forgetting to wrap substitutions in a Lookup; passing a tuple instead of list; mixing in output of another library.","solutions":["Wrap plain text in Line(): content = [Line('# my comment'), ...].","Wrap substitution rules in ast.Lookup(...) or use ast.subst()/ast.subst_liga() helpers that return supported objects.","Ensure custom content classes implement .state() returning Line(s).","Flatten nested lists yourself before assigning content (list comprehension over sublists)."],"exampleFix":"// before\nFeature(id=1, desc='...', content=['# comment', subst(...)], ...)\n// after\nFeature(id=1, desc='...', content=[Line('# comment'), subst(...)], ...)","handlingStrategy":"validation","validationCode":"def validate_content(content):\n    for item in content:\n        if not (isinstance(item, (ast.Line, ast.Lookup, ast.Feature)) or hasattr(item, 'state')):\n            raise TypeError(f'{item!r} must be Line, Lookup, Feature, or expose .state()')\n\nvalidate_content(my_content)\nfeature = FeatureWithDocs(id=1, desc='d', content=my_content, version='1.0', example='e')","typeGuard":"def is_valid_content_item(item) -> bool:\n    return isinstance(item, (ast.Line, ast.Lookup, ast.Feature)) or callable(getattr(item, 'state', None))","tryCatchPattern":"try:\n    lines = feature.state()\nexcept TypeError as e:\n    if 'Invalid item to flatten' in str(e):\n        bad = str(e).split(': ', 1)[1]\n        logging.error(f'replace {bad!r} with Line()/Lookup() wrapper')\n    else:\n        raise","preventionTips":["Always wrap raw strings in ast.Line(...) and rules in ast.Lookup(...).","Use ast.subst/subst_liga helpers so content items are always the right type.","Give custom content classes a .state() method returning Line objects."],"tags":["python","typeerror","content-model","feature","fea-generation"],"backgroundTag":"invalid-content-item","analyzedSha":"c08fda97fef73d68c1755219852150770f6e6578","analyzedAt":"2026-08-28T22:07:29.503Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}