oraios/serena · error

Unhandled comment normalisation: {comment_normalisation}

Error message

Unhandled comment normalisation: {comment_normalisation}

What it means

normalise_yaml_comments dispatches on a YamlCommentNormalisation enum value; the `case _:` branch raises ValueError when the supplied value is not one of the handled normalisation modes. Since the value is expected to be an enum member, hitting this indicates a non-enum or out-of-range value was passed.

Source

Thrown at src/serena/util/yaml.py:209

                                # and adding an empty line at the beginning instead
                                if preceding_comment is not None and yaml_comment_entry_is_empty(
                                    preceding_comment[ITEM_COMMENT_INDEX_BEFORE]
                                ):
                                    last_token.value = last_token.value[:-1]

                                    first_token = token_list[0]
                                    if isinstance(first_token, CommentToken):
                                        if not first_token.value.startswith("\n"):
                                            first_token.value = "\n" + first_token.value

                                    preceding_comment[ITEM_COMMENT_INDEX_BEFORE] = token_list
                                    current_comment[ITEM_COMMENT_INDEX_BEFORE] = None
                    preceding_comment = current_comment

            # remove nested comments, as we assume that only top-level keys are supposed to be commented
            remove_nested_comments()
        case _:
            raise ValueError(f"Unhandled comment normalisation: {comment_normalisation}")


def save_yaml(path: str, data: dict | CommentedMap, preserve_comments: bool = True) -> None:
    yaml = _create_yaml(preserve_comments)
    target_dir = os.path.dirname(path)
    os.makedirs(target_dir, exist_ok=True)
    # Atomic write: dump to a temp file in the SAME directory, then os.replace onto the target.
    # A plain truncate-and-write (open(path, "w")) is NOT atomic: a concurrent writer (e.g. a second
    # Serena process updating the auto-managed registered-projects list) or an interrupted write can
    # leave the file half-overwritten — writing a shorter value over a longer one leaves a stale tail,
    # which corrupts the YAML so it no longer parses and every later load fails. temp + os.replace makes
    # each write all-or-nothing (last-writer-wins, never a corrupt interleave).
    fd, tmp = tempfile.mkstemp(dir=target_dir, prefix=os.path.basename(path) + ".", suffix=".tmp")
    try:
        with os.fdopen(fd, "w", encoding=SERENA_FILE_ENCODING) as f:
            yaml.dump(data, f)
        _replace_with_retry(tmp, path)
    except BaseException:

View on GitHub (pinned to 7fcbca7e62)

Solutions

  1. Import YamlCommentNormalisation from serena.util.yaml and pass an enum member (e.g. YamlCommentNormalisation.LEADING), not a string.
  2. Check the enum definition for the exact accepted values in the installed version.
  3. Audit call sites for values loaded from external config/user input that bypass the enum.

Example fix

// before
normalise_yaml_comments(data, 'leading')
// after
from serena.util.yaml import YamlCommentNormalisation
normalise_yaml_comments(data, YamlCommentNormalisation.LEADING)
Defensive patterns

Strategy: validation

Validate before calling

from serena.util.yaml import YamlCommentNormalisation

def assert_valid_normalisation(mode) -> None:
    if not isinstance(mode, YamlCommentNormalisation):
        raise TypeError(f"comment_normalisation must be a YamlCommentNormalisation, got {type(mode).__name__}")

Type guard

def is_comment_normalisation(value) -> bool:
    return isinstance(value, YamlCommentNormalisation)

Try / catch

try:
    normalise_yaml_comments(data, mode)
except ValueError as e:
    if str(e).startswith('Unhandled comment normalisation'):
        mode = YamlCommentNormalisation(mode)  # coerce strings if possible
        normalise_yaml_comments(data, mode)
    else:
        raise

Prevention

When it happens

Trigger: Calling normalise_yaml_comments (public) with a comment_normalisation argument that is not a member of YamlCommentNormalisation — e.g. a raw string like 'leading', an int, or an enum from a different/older version.

Common situations: Programmatic config manipulation passing a string instead of the enum; version drift where an enum value was renamed or removed between releases.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29). Data as JSON: /api/errors/8569b46c4934bb51. Report an issue: GitHub.