{"record":{"id":"bc97c37c83a9feae","repo":"xai-org/x-algorithm","slug":"not-a-parquet-path-batch-file-path","errorCode":null,"errorMessage":"not a parquet path: {batch_file_path}","messagePattern":"not a parquet path: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"phoenix/xrex/data/conversion_labels.py","lineNumber":48,"sourceCode":"        (n for n in names if n.startswith(ACTION_DELAY_PREFIX)),\n        key=lambda n: int(n[len(ACTION_DELAY_PREFIX) :]),\n    )\n\n\ndef action_index_of(column: str) -> int:\n    if not column.startswith(ACTION_DELAY_PREFIX):\n        raise ValueError(f\"not an action delay column: {column}\")\n    return int(column[len(ACTION_DELAY_PREFIX) :])\n\n\ndef sidecar_path_for(batch_file_path: str) -> str:\n    m = _PARTITION_SEG_RE.search(batch_file_path)\n    if m is None:\n        raise ValueError(f\"not a partition batch file path: {batch_file_path}\")\n    root = batch_file_path[: m.start()]\n    rel = batch_file_path[m.start() :]\n    if not rel.endswith(\".parquet\"):\n        raise ValueError(f\"not a parquet path: {batch_file_path}\")\n    return os.path.join(root, \"labels\", rel[: -len(\".parquet\")] + \".labels.parquet\")\n\n\ndef load_sidecar_delays(\n    sidecar_path: str, columns: list[str] | None = None\n) -> dict[str, np.ndarray]:\n    columns = columns or [DELAY_COLUMN]\n    schema_names = pq.ParquetFile(sidecar_path).schema_arrow.names\n    missing = [c for c in columns if c not in schema_names]\n    if missing:\n        raise ValueError(\n            f\"sidecar {sidecar_path} missing column(s) {missing}; available: {schema_names}\"\n        )\n    t = pq.read_table(sidecar_path, columns=columns)\n    out: dict[str, np.ndarray] = {}\n    for name in columns:\n        col = t.column(name).combine_chunks()\n        if isinstance(col, pa.ChunkedArray):","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/phoenix/xrex/data/conversion_labels.py#L30-L66","documentation":"After locating the partition segment in the batch path, sidecar_path_for() requires the relative remainder to end with '.parquet' so it can derive the '.labels.parquet' sidecar name. A path whose filename lacks the .parquet extension cannot be mapped to a sidecar, so ValueError is raised. This is a weaker check that catches directories, temp files, and non-parquet inputs.","triggerScenarios":"Calling sidecar_path_for('.../date=2026-08-28/hour=13/batch-0007.snappy') or with a '.csv', '.arrow', partially-written '.parquet.tmp', or a directory path ending in a partition segment.","commonSituations":"Index files listing temporary or in-progress files that were later renamed; hand-built paths with wrong extensions; passing a partition directory instead of a file.","solutions":["Pass the final, fully-written .parquet batch file path.","Filter index/metadata listings to only '*.parquet' entries.","Wait for writers to finish renaming temp files before the loader discovers them."],"exampleFix":"// before\nsidecar_path_for('/d/date=2026-08-28/hour=13/batch-0007.tmp')  # ValueError\n\n// after\nsidecar_path_for('/d/date=2026-08-28/hour=13/batch-0007.parquet')","handlingStrategy":"validation","validationCode":"def usable_batch_path(p: str) -> bool:\n    return p.endswith('.parquet') and PARTITION_SEG.search(p) is not None","typeGuard":"def is_parquet_partition_file(p: str) -> bool:\n    return p.endswith('.parquet') and bool(PARTITION_SEG.search(p))","tryCatchPattern":"try:\n    sidecar = sidecar_path_for(p)\nexcept ValueError:\n    continue  # skip temp/non-parquet entries","preventionTips":["Filter discovered files with glob('**/*.parquet') before passing paths.","Ignore in-progress '.tmp' files in discovery logic."],"tags":["paths","file-extension","parquet","conversion-labels"],"backgroundTag":"invalid-file-path","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}