{"record":{"id":"4d9faa72408bf6d0","repo":"unslothai/unsloth","slug":"mode-title-training-requires-at-least-one-string","errorCode":null,"errorMessage":"{mode_title} training requires at least one string 'text' value in {split_scope}; all {dropped_rows} rows were null or non-string.","messagePattern":"(.+?) training requires at least one string 'text' value in (.+?); all (.+?) rows were null or non-string\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"studio/backend/utils/datasets/raw_text.py","lineNumber":97,"sourceCode":"    # dropped rows or verify the result is non-empty without consuming the whole\n    # stream. Keep the filter, skip only the len()-based diagnostics.\n    if not hasattr(dataset, \"__len__\"):\n        return filtered_dataset, [\n            RawTextNotice(\n                message = (\n                    f\"{mode_title}: streaming dataset — rows with null or \"\n                    f\"non-string 'text' in {split_scope} are dropped on the fly.\"\n                ),\n                level = \"info\",\n            )\n        ]\n\n    dropped_rows = len(dataset) - len(filtered_dataset)\n    if not dropped_rows:\n        return filtered_dataset, []\n\n    if len(filtered_dataset) == 0:\n        raise ValueError(\n            f\"{mode_title} training requires at least one string 'text' value \"\n            f\"in {split_scope}; all {dropped_rows} rows were null or non-string.\"\n        )\n\n    return filtered_dataset, [\n        RawTextNotice(\n            message = (\n                f\"{mode_title}: dropped {dropped_rows:,} row(s) with null or \"\n                f\"non-string 'text' values from {split_scope}\"\n            ),\n            level = \"warning\",\n            update_status = True,\n        )\n    ]\n\n\ndef prepare_raw_text_dataset(\n    dataset: Dataset,","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/utils/datasets/raw_text.py#L79-L115","documentation":"Raised by raw-text dataset preparation after filtering: every row in the split had a null or non-string 'text' value, so the filtered dataset is empty and the requested training mode has nothing to train on. Partial drops only produce a warning notice; only the all-rows-dropped case raises. The message includes the mode title and split scope for context.","triggerScenarios":"Calling raw text preparation on a dataset whose 'text' column is entirely null, or typed as non-string (e.g. all ints/floats/lists), for the selected split. For streaming datasets this error cannot fire (rows are dropped on the fly with an info notice instead).","commonSituations":"Dataset loaded with the wrong split that happens to have no text (e.g. a metadata-only aux split); text stored under a different column name while 'text' exists but is null; parquet column typed as binary/list after a bad conversion; user selected 'test' split of a dataset that only populates 'train'.","solutions":["Inspect the split: ds['text'] dtype and null count (e.g. sum of nulls) to confirm it is entirely empty/non-string.","Select a split that actually contains text (usually 'train').","If the text lives under another column, rename it to 'text' or rely on the auto-select path when no 'text' column exists at all.","Cast non-string columns (e.g. int labels) with .cast_column('text', Value('string')) only if the values genuinely are text mislabeled by schema.","Re-export the dataset from source with correct types."],"exampleFix":"# before\nresult = prepare_raw_text(ds.select_columns([\"text\"]))  # 'text' all NULL -> ValueError\n\n# after\nresult = prepare_raw_text(ds.rename_column(\"body\", \"text\"))  # real text column","handlingStrategy":"validation","validationCode":"def split_has_string_text(ds, text_column=\"text\") -> bool:\n    col = ds[text_column]\n    non_null = [v for v in col if isinstance(v, str) and v]\n    return len(non_null) > 0\n\n# guard: assert split_has_string_text(ds[split]) before prepare_raw_text","typeGuard":"def has_usable_text_column(dataset, column=\"text\") -> bool:\n    feats = dataset.features\n    return column in feats and len(dataset.filter(\n        lambda r: isinstance(r[column], str) and r[column].strip(), load_from_cache_file=False\n    )) > 0","tryCatchPattern":"try:\n    filtered, notices = prepare_raw_text(ds, split_name=split)\nexcept ValueError as e:\n    if \"requires at least one string\" in str(e):\n        ds = ds.rename_column(real_text_col, \"text\")\n        filtered, notices = prepare_raw_text(ds, split_name=split)\n    else:\n        raise","preventionTips":["Check null counts and dtype of 'text' per split before training.","For streaming datasets rely on the on-the-fly drop notice instead of pre-filtering.","Rename the true text column to 'text' at load time.","Sanity-check that the chosen split actually contains data (len(ds[split]) > 0)."],"tags":["dataset","raw-text","training-data","validation"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}