{"record":{"id":"3b52b0a2e03a0ed4","repo":"mlflow/mlflow","slug":"malformed-metric-line-metric-line-r","errorCode":null,"errorMessage":"Malformed metric line: {metric_line!r}","messagePattern":"Malformed metric line: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"mlflow/store/fs2db/_tracking.py","lineNumber":229,"sourceCode":"\n\ndef _sanitize_metric_value(val: float) -> tuple[bool, float]:\n    is_nan = math.isnan(val)\n    if is_nan:\n        return True, 0.0\n    if math.isinf(val):\n        return False, 1.7976931348623157e308 if val > 0 else -1.7976931348623157e308\n    return False, val\n\n\ndef _parse_metric_line(metric_line: str) -> tuple[int, float, int]:\n    match metric_line.strip().split(\" \"):\n        case [ts, val]:\n            return int(ts), float(val), 0\n        case [ts, val, step, *_]:\n            return int(ts), float(val), int(step)\n        case _:\n            raise ValueError(f\"Malformed metric line: {metric_line!r}\")\n\n\ndef _migrate_run_metrics(\n    session: Session,\n    metrics_dir: Path,\n    run_uuid: str,\n    stats: MigrationStats,\n    *,\n    batch_size: int = 5000,\n) -> None:\n    all_metrics = read_metric_lines(metrics_dir)\n    count = 0\n\n    for key, lines in all_metrics.items():\n        # Track the \"latest\" metric for this key: max by (step, timestamp, value)\n        latest: tuple[int, int, float] | None = None  # (step, timestamp, value)\n        latest_is_nan = False\n","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/mlflow/mlflow/blob/6a27f2decc0b76eb1b54af31849784addb357dbc/mlflow/store/fs2db/_tracking.py#L211-L247","documentation":"Filesystem tracking stores persist metrics as text lines of the form 'timestamp value [step]'. _parse_metric_line uses structural pattern matching to parse each line; a line that doesn't split into 2+ space-separated tokens (or has unparseable tokens) raises ValueError, surfacing a corrupted or non-MLflow metric file during fs2db migration.","triggerScenarios":"Migrating a filesystem store whose metrics/<metric> files contain blank lines, extra malformed tokens handled by the catch-all, or corrupted/truncated content that fails int()/float() conversion.","commonSituations":"Manually edited or truncated metric files; files written by third-party tools into mlruns; interrupted writes leaving partial lines; copying mlruns with corruption.","solutions":["Open the offending metrics file (the path is in the migration log) and fix or remove the malformed line.","Remove/repair corrupted metric files for the affected run, or exclude that run from migration.","Regenerate the metrics by re-running the training/logging job if the source data is unavailable."],"exampleFix":"# before (metrics/epoch_acc)\n1627584.5 0.93\n\n\n# after (blank lines removed)\n1627584.5 0.93","handlingStrategy":"validation","validationCode":"def validate_metric_file(path):\n    for i, line in enumerate(open(path), 1):\n        parts = line.strip().split(\" \")\n        if len(parts) < 2:\n            raise SystemExit(f\"{path}:{i}: malformed metric line {line!r}\")\n        int(parts[0]); float(parts[1])\n        if len(parts) > 2:\n            int(parts[2])","typeGuard":"def is_valid_metric_line(line: str) -> bool:\n    parts = line.strip().split(\" \")\n    try:\n        int(parts[0]); float(parts[1])\n        if len(parts) > 2: int(parts[2])\n        return True\n    except (ValueError, IndexError):\n        return False","tryCatchPattern":"try:\n    migrate(engine, source)\nexcept ValueError as e:\n    if \"Malformed metric line\" in str(e):\n        logger.error(\"Corrupt metric data in source store: %s\", e)\n    else:\n        raise","preventionTips":["Never hand-edit files under mlruns/*/metrics","Check run health (search_runs) before migrating; repair corrupt runs first","Copy filesystem stores with rsync to avoid truncated files"],"tags":["migration","parsing","data-corruption","metrics"],"backgroundTag":"malformed-input-data","analyzedSha":"6a27f2decc0b76eb1b54af31849784addb357dbc","analyzedAt":"2026-08-29T20:54:51.419Z","schemaVersion":2},"datasetVersion":"2026-08-29T22:17:34.462Z"}