{"record":{"id":"76c0a0bac540c969","repo":"subframe7536/maple-font","slug":"length-of-content-glyphs-len-must-be-equal-t","errorCode":null,"errorMessage":"length of `content` ({glyphs_len}) must be equal to length of `target` ({target_len}).","messagePattern":"length of `content` \\((.+?)\\) must be equal to length of `target` \\((.+?)\\)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"source/py/feature/calt/tag.py","lineNumber":161,"sourceCode":"                - End with one of [\"<\", \">\", \"(\", \")\", \"[\", \"]\"]\n                - Middle characters must be ASCII letters\n\n        bg_cls_dict (dict[str, ast.Clazz]): Dictionary mapping uppercase letters to background\n            class definitions\n    Returns:\n        ast.Lookup: A Lookup object containing the substitution rules, named with pattern\n            \"custom_tag_{target middle chars}\".\n    Example:\n        >>> tag_custom(\"_TODO_\", \"(TODO)\")\n    \"\"\"\n    result = []\n    for source, target in content_list:\n        glyphs = list(source)\n        glyphs_len = len(glyphs)\n        target_len = len(target)\n\n        if target_len != glyphs_len:\n            raise ValueError(\n                f\"length of `content` ({glyphs_len}) must be equal to length of `target` ({target_len}).\"\n            )\n        if target[-1] not in __map:\n            raise ValueError(\n                f\"Last letter of `target` must in {list(__map.keys())}, current is '{target[-1]}'\"\n            )\n\n        # Parse source\n        source_list = []\n        for g in glyphs:\n            if g.isalpha():\n                source_list.append(f\"@{g.upper()}\")\n            else:\n                source_list.append(ast.gly(g))\n\n        # Parse target\n        target_list = []\n        for target_gly in target:","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/subframe7536/maple-font/blob/c08fda97fef73d68c1755219852150770f6e6578/source/py/feature/calt/tag.py#L143-L179","documentation":"tag_custom() builds custom tag ligature lookups where each source glyph is progressively substituted toward a target pattern; this only works when the source string and target pattern have the same number of characters, since they map 1:1 glyph by glyph. When len(source) != len(target), a positional mapping is impossible and ValueError is raised. This is validated first, before any other target checks.","triggerScenarios":"Calling tag_custom(content_list=[(src, tgt)], ...) where any tuple has len(src) != len(tgt), e.g. ('_TODO_', '(TODO!)') — source 5 chars vs target 6 chars.","commonSituations":"Designing a custom tag where the bracket style adds/removes characters relative to the source; typos in the target string; auto-generating pairs from config where source and target were edited independently.","solutions":["Make source and target exactly the same length — each source glyph maps to one target glyph.","Pad the source with placeholder glyphs or drop extra target characters to equalize lengths.","Pre-validate each (source, target) pair with `assert len(source) == len(target)` before calling.","Split a longer tag into separate same-length tag_custom calls if needed."],"exampleFix":"// before\ntag_custom([('_TODO_', '(TODO!)')], bg_cls_dict)  # 5 vs 6\n// after\ntag_custom([('_TODO_', '(TODO)')], bg_cls_dict)  # both length 5","handlingStrategy":"validation","validationCode":"def validate_tag_pairs(content_list):\n    for src, tgt in content_list:\n        if len(src) != len(tgt):\n            raise ValueError(f'pair {src!r}/{tgt!r}: len {len(src)} != {len(tgt)}')\n\nvalidate_tag_pairs(content_list)\nlookup = tag_custom(content_list, bg_cls_dict)","typeGuard":"def is_equal_length_pair(pair: tuple[str, str]) -> bool:\n    return len(pair[0]) == len(pair[1])","tryCatchPattern":"try:\n    lookup = tag_custom(content_list, bg_cls_dict)\nexcept ValueError as e:\n    if 'must be equal to length of' in str(e):\n        content_list = [(s, t[:len(s)]) for s, t in content_list]\n        lookup = tag_custom(content_list, bg_cls_dict)\n    else:\n        raise","preventionTips":["Design source and target patterns as strict 1:1 character mappings.","Unit-test each (source, target) pair for equal length before builds.","When generating pairs from config, diff source/target lengths in CI."],"tags":["python","valueerror","length-mismatch","custom-tags","ligature"],"backgroundTag":"length-mismatch","analyzedSha":"c08fda97fef73d68c1755219852150770f6e6578","analyzedAt":"2026-08-28T22:07:29.503Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}