"""Error formatting helpers for ComfyUI JSON nodes.""" from __future__ import annotations from typing import Any def push_error( errors: list[dict[str, str]], path: str, message: str, code: str = "validation_error", **details: str, ) -> None: error = {"path": path, "message": message, "code": code} error.update({key: value for key, value in details.items() if value is not None}) errors.append(error) def display_path(path: str) -> str: """Strip the root '$.' prefix for cleaner user-facing paths.""" if path.startswith("$."): return path[2:] return path if path != "$" else "" def truncate_repr(value: Any, max_length: int = 50) -> str: text = repr(value) if len(text) <= max_length: return text return f"{text[:max_length]}..." def format_error_line(error: dict[str, str]) -> str: code = error.get("code", "validation_error") path = display_path(error.get("path", "$")) message = error.get("message", "Validation error") if code == "required_missing": return f"Missing required field `{path}`." if code == "unexpected_key": return f"Field `{path}` does not match the schema." if code == "type_mismatch": return f"Type mismatch at `{path}`. {message}." if code == "enum_mismatch": return f"Enum mismatch at `{path}`. {message}." if code == "pattern_mismatch": return f"Pattern mismatch at `{path}`. {message}." if code == "duplicate_key": return message if code == "invalid_json": return f"Invalid JSON at `{path}`. {message}." if code == "invalid_object": return f"Expected JSON object at `{path}`." if code in {"invalid_schema", "invalid_schema_json"}: return f"Schema error at `{path}`. {message}." return f"{message} (`{path}`)" def errors_text(errors: list[dict[str, str]]) -> str: if not errors: return "" lines = ["JSON validation failed:"] for error in errors: lines.append(f"- {format_error_line(error)}") return "\n".join(lines)