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
- Import YamlCommentNormalisation from serena.util.yaml and pass an enum member (e.g. YamlCommentNormalisation.LEADING), not a string.
- Check the enum definition for the exact accepted values in the installed version.
- 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
- Always pass enum members, never raw strings, for comment_normalisation.
- Use typing.Literal[YamlCommentNormalisation] annotations on wrapper functions.
- When upgrading the library, grep for YamlCommentNormalisation usages against the current enum.
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
- Unknown token count estimator: {self}
- Unknown language backend '{backend_str}': valid values are {
- Invalid line_ending: {value!r}. Valid values are: {valid}
- Invalid language server: '{orig_language_str}'.\nValid value
- Error loading Serena configuration from {config_file_path}:
AI-assisted analysis of oraios/serena@7fcbca7e62 (2026-08-29).
Data as JSON: /api/errors/8569b46c4934bb51.
Report an issue: GitHub.