{"record":{"id":"adab75c959761fd4","repo":"subframe7536/maple-font","slug":"last-letter-of-target-must-in-list-map-keys","errorCode":null,"errorMessage":"Last letter of `target` must in {list(__map.keys())}, current is '{target[-1]}'","messagePattern":"Last letter of `target` must in (.+?), current is '(.+?)'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"source/py/feature/calt/tag.py","lineNumber":165,"sourceCode":"            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:\n            if target_gly in __map:\n                target_list.append(f\"{__map[target_gly]}.bg\")\n            elif target_gly.isalpha():\n                up = target_gly.upper()","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/subframe7536/maple-font/blob/c08fda97fef73d68c1755219852150770f6e6578/source/py/feature/calt/tag.py#L147-L183","documentation":"In tag_custom(), the final character of each target pattern must be one of the closing/sharp bracket glyphs mapped in __map: '<', '>', '(', ')', '[', ']'. These map to the start/end glyph classes used to build the substitution chain. If target[-1] is anything else (letter, underscore, digit, punctuation like '!'), ValueError is raised. Note target[-1] also implies an empty target would raise IndexError first, so targets must be non-empty too.","triggerScenarios":"Calling tag_custom with a target whose last character is not in ['<','>','(',')','[',']'], e.g. ('_TODO_', 'TODO!') or ('__', '_DONE_') ending in underscore.","commonSituations":"Forgetting the closing bracket of the visual tag design; using ASCII-only tags without decorative brackets; generating targets programmatically and dropping the final bracket character.","solutions":["End the target with one of < > ( ) [ ] — e.g. '(TODO)', '[DEBUG]', '<WARN>'.","Add the missing closing bracket character to the target string.","If you need a new terminator style, extend the __map dict in source/py/feature/calt/tag.py:123.","Pre-validate: `assert target and target[-1] in '<>()[]'` before calling."],"exampleFix":"// before\ntag_custom([('_TODO_', 'TODO')], bg_cls_dict)\n// after\ntag_custom([('_TODO_', '(TODO)')], bg_cls_dict)","handlingStrategy":"validation","validationCode":"VALID_TERMINATORS = '<>()[]'\ndef validate_target(tgt):\n    if not tgt or tgt[-1] not in VALID_TERMINATORS:\n        raise ValueError(f'target {tgt!r} must end with one of {VALID_TERMINATORS}')\n\nfor _, tgt in content_list:\n    validate_target(tgt)\ntag_custom(content_list, bg_cls_dict)","typeGuard":"def has_valid_terminator(tgt: str) -> bool:\n    return bool(tgt) and tgt[-1] in '<>()[]'","tryCatchPattern":"try:\n    lookup = tag_custom(content_list, bg_cls_dict)\nexcept ValueError as e:\n    if 'Last letter of `target`' in str(e):\n        content_list = [(s, t + ')') for s, t in content_list if not has_valid_terminator(t)]\n        lookup = tag_custom(content_list, bg_cls_dict)\n    else:\n        raise","preventionTips":["Always end custom tag targets with a bracket character from < > ( ) [ ].","Keep a shared constant of valid terminators in your config generator.","Remember targets must also be non-empty and same length as source."],"tags":["python","valueerror","custom-tags","invalid-character","ligature"],"backgroundTag":"invalid-tag-terminator","analyzedSha":"c08fda97fef73d68c1755219852150770f6e6578","analyzedAt":"2026-08-28T22:07:29.503Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}