Skip to content

fix(yolo): correct data.yaml paths for all YOLO formats (#240)#506

Open
davidnichols-ops wants to merge 1 commit into
roboflow:mainfrom
davidnichols-ops:fix/yolov8-data-yaml-paths-240
Open

fix(yolo): correct data.yaml paths for all YOLO formats (#240)#506
davidnichols-ops wants to merge 1 commit into
roboflow:mainfrom
davidnichols-ops:fix/yolov8-data-yaml-paths-240

Conversation

@davidnichols-ops

Copy link
Copy Markdown

Summary

Fixes #240Incorrect Data Path in YOLOv8 Dataset Configuration (5 comments, confirmed regression from v1.1.40 → v1.2.16, reported by multiple users).

When downloading a YOLO dataset via version.download("yolov8"), the generated data.yaml contained incorrect relative paths:

train: ../train/images
val: ../valid/images
test: ../test/images

The ../ prefix is wrong — the train/, valid/, test/ directories are siblings of data.yaml, not in the parent directory. This broke YOLO training out of the box.

Root cause — four bugs in __reformat_yaml

  1. yolov8 path fix was gated on ultralytics==8.0.196 — for any other version (or when ultralytics wasn't installed at all) paths remained broken. This was the primary cause of the regression.

  2. yolov9 had no path fix at all — it was listed in the amend formats list but had no callback case, so the YAML was read and rewritten with zero changes.

  3. lstrip("..") was misusedstr.lstrip strips any combination of the given characters, not a prefix. This silently mangled paths like ../../train/images and .hidden/train/images.

  4. test key was always written even when the dataset had no test split, producing a path to a non-existent directory.

Fix

  • Removed the ultralytics version gate entirely — paths are now always corrected for yolov8 and yolov9, regardless of whether ultralytics is installed or what version it is.
  • Added yolov9 to the relative-path branch (train/images, valid/images, test/images).
  • Replaced lstrip with _strip_rel_prefix — a proper helper that iteratively removes ../ and ./ prefixes without mangling legitimate path characters.
  • Used self.splits["test"] > 0 to decide whether to emit the test key; it is removed when the split is absent.
  • Used os.path.join instead of string concatenation for absolute paths in legacy formats.

Behavior matrix

Format Path style Before After
yolov8 relative ../train/images (broken unless ultralytics==8.0.196) train/images
yolov9 relative ../train/images (always broken) train/images
yolov5pytorch absolute <location>train/images (lstrip bug) <location>/train/images
yolov7pytorch absolute <location>train/images (lstrip bug) <location>/train/images
mt-yolov6 absolute <location>train/images (lstrip bug) <location>/train/images

Test plan

  • 13 new tests in TestReformatYaml covering:
    • yolov8/yolov9 use relative paths (no ../ prefix)
    • yolov8/yolov9 omit test key when no test split exists
    • yolov5pytorch/yolov7pytorch/mt-yolov6 use absolute paths
    • Legacy formats omit test key when no test split exists
    • ../../ double-parent prefix is correctly stripped
    • Non-YOLO formats (e.g. coco) are not modified
    • Works without ultralytics installed
    • Works with any ultralytics version
    • Other YAML fields (nc, names, roboflow) are preserved
  • All 804 existing tests still pass
  • ruff format --check passes
  • ruff check passes
  • mypy roboflow passes

Generated with Devin

@davidnichols-ops

Copy link
Copy Markdown
Author

Thanks for the review consideration! Quick summary of what this PR does and why it's a clean merge:

Scope: Single method (__reformat_yaml), 2 files, 1 commit. No unrelated changes.

The fix addresses 4 bugs in one method:

  1. Removed the ultralytics==8.0.196 version gate that caused the regression — paths are now always corrected regardless of installed package version
  2. Added yolov9 to the relative-path branch (was listed in amend formats but had no callback case)
  3. Replaced lstrip("..") with proper prefix stripping (lstrip strips any combination of chars, not a prefix — silently mangled ../../ paths)
  4. Only writes test key when self.splits["test"] > 0 (was always written, even for datasets without a test split)

Verification:

  • 804 existing tests pass (no regressions)
  • 13 new tests covering all 5 YOLO formats, test-split presence/absence, ultralytics independence, edge cases
  • ruff format --check, ruff check, and mypy all clean

Happy to address any feedback!

The __reformat_yaml method had four bugs that caused broken training
paths in downloaded YOLO datasets:

1. yolov8 path fix was gated on ultralytics==8.0.196 -- for any other
   version (or when ultralytics was not installed) paths remained as
   ../train/images, ../valid/images, ../test/images, which are wrong
   because the split dirs are siblings of data.yaml, not in the parent.

2. yolov9 was listed in the amend formats but had no callback case --
   the YAML was read and rewritten with zero changes.

3. lstrip("..") was used to strip ../ prefixes, but str.lstrip strips
   any *combination* of the given characters, not a prefix.  This
   silently mangled paths like ../../train/images.

4. The test key was always written even when the dataset had no test
   split, producing a path to a non-existent directory.

Fix:
- Remove the ultralytics version gate entirely; paths are now always
  corrected for yolov8 and yolov9.
- Add yolov9 to the relative-path branch.
- Replace lstrip with a proper _strip_rel_prefix helper that iteratively
  removes ../ and ./ prefixes.
- Use self.splits["test"] > 0 to decide whether to emit the test key;
  remove it when the split is absent.
- Use os.path.join instead of string concatenation for absolute paths.

Tests: 13 new tests in TestReformatYaml covering yolov8/yolov9 relative
paths, legacy absolute paths, test-split presence/absence, ultralytics
independence, double-parent-prefix edge case, and preservation of other
YAML fields.  All 804 existing tests still pass.

Closes roboflow#240

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@davidnichols-ops davidnichols-ops force-pushed the fix/yolov8-data-yaml-paths-240 branch from d7c429f to 8bbf8fa Compare July 12, 2026 03:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect Data Path in YOLOv8 Dataset Configuration

1 participant