subframe7536/maple-font · error · ValueError

length of `content` ({glyphs_len}) must be equal to length o

Error message

length of `content` ({glyphs_len}) must be equal to length of `target` ({target_len}).

What it means

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.

Source

Thrown at source/py/feature/calt/tag.py:161

                - End with one of ["<", ">", "(", ")", "[", "]"]
                - Middle characters must be ASCII letters

        bg_cls_dict (dict[str, ast.Clazz]): Dictionary mapping uppercase letters to background
            class definitions
    Returns:
        ast.Lookup: A Lookup object containing the substitution rules, named with pattern
            "custom_tag_{target middle chars}".
    Example:
        >>> tag_custom("_TODO_", "(TODO)")
    """
    result = []
    for source, target in content_list:
        glyphs = list(source)
        glyphs_len = len(glyphs)
        target_len = len(target)

        if target_len != glyphs_len:
            raise ValueError(
                f"length of `content` ({glyphs_len}) must be equal to length of `target` ({target_len})."
            )
        if target[-1] not in __map:
            raise ValueError(
                f"Last letter of `target` must in {list(__map.keys())}, current is '{target[-1]}'"
            )

        # Parse source
        source_list = []
        for g in glyphs:
            if g.isalpha():
                source_list.append(f"@{g.upper()}")
            else:
                source_list.append(ast.gly(g))

        # Parse target
        target_list = []
        for target_gly in target:

View on GitHub (pinned to c08fda97fe)

Solutions

  1. Make source and target exactly the same length — each source glyph maps to one target glyph.
  2. Pad the source with placeholder glyphs or drop extra target characters to equalize lengths.
  3. Pre-validate each (source, target) pair with `assert len(source) == len(target)` before calling.
  4. Split a longer tag into separate same-length tag_custom calls if needed.

Example fix

// before
tag_custom([('_TODO_', '(TODO!)')], bg_cls_dict)  # 5 vs 6
// after
tag_custom([('_TODO_', '(TODO)')], bg_cls_dict)  # both length 5
Defensive patterns

Strategy: validation

Validate before calling

def validate_tag_pairs(content_list):
    for src, tgt in content_list:
        if len(src) != len(tgt):
            raise ValueError(f'pair {src!r}/{tgt!r}: len {len(src)} != {len(tgt)}')

validate_tag_pairs(content_list)
lookup = tag_custom(content_list, bg_cls_dict)

Type guard

def is_equal_length_pair(pair: tuple[str, str]) -> bool:
    return len(pair[0]) == len(pair[1])

Try / catch

try:
    lookup = tag_custom(content_list, bg_cls_dict)
except ValueError as e:
    if 'must be equal to length of' in str(e):
        content_list = [(s, t[:len(s)]) for s, t in content_list]
        lookup = tag_custom(content_list, bg_cls_dict)
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of subframe7536/maple-font@c08fda97fe (2026-08-28). Data as JSON: /api/errors/76c0a0bac540c969. Report an issue: GitHub.