unslothai/unsloth · error · HTTPException

{str(exc)}

Error message

{str(exc)}

What it means

HTTP 400 raised when `verify_native_path_lease` rejects the submitted native path lease for a dataset import. The lease is a signed/scoped grant (operation=dataset-import, kind=dataset, path_type=file, suffixes limited to LOCAL_UPLOAD_EXTS) and its error string is surfaced verbatim, so the detail text pinpoints which constraint failed: expired, tampered, wrong operation, wrong kind, wrong path type, or disallowed suffix.

Source

Thrown at studio/backend/hub/services/datasets/local.py:322

    ensure_dir(DATASET_UPLOAD_DIR)
    stem = Path(filename).stem
    stored_name = f"{uuid.uuid4().hex}_{stem}{ext}"
    return filename, DATASET_UPLOAD_DIR / stored_name, max_bytes, max_label


def _native_upload_dataset_response(native_path_lease: str) -> UploadDatasetResponse:
    from utils.native_path_leases import NativePathLeaseError, verify_native_path_lease

    try:
        grant = verify_native_path_lease(
            native_path_lease,
            operation = "dataset-import",
            expected_kind = "dataset",
            expected_path_type = "file",
            allowed_suffixes = sorted(LOCAL_UPLOAD_EXTS),
        )
    except NativePathLeaseError as exc:
        raise HTTPException(status_code = 400, detail = str(exc)) from exc

    filename, stored_path, max_bytes, max_label = _upload_destination(grant.canonical_path.name)
    if grant.size_bytes is not None and grant.size_bytes > max_bytes:
        raise _upload_too_large(max_label)

    written = 0
    upload_complete = False
    try:
        with open(grant.canonical_path, "rb") as source, open(stored_path, "wb") as target:
            while chunk := source.read(LOCAL_UPLOAD_CHUNK_BYTES):
                written += len(chunk)
                if written > max_bytes:
                    raise _upload_too_large(max_label)
                target.write(chunk)
        upload_complete = True
    except OSError as exc:
        raise HTTPException(
            status_code = 400,

View on GitHub (pinned to 203007d190)

Solutions

  1. Read the verbatim NativePathLeaseError message — it names the exact failed check (expiry, operation, kind, suffix, path).
  2. Re-select the file in the native picker to mint a fresh lease and submit immediately.
  3. Make sure the file still exists with the same name and an allowed extension at import time.
  4. Do not cache or persist leases across sessions; they are single-purpose and short-lived by design.
Defensive patterns

Strategy: validation

Validate before calling

# Mint the lease and use it in the same user gesture; never persist it
lease = pick_native_file(allowed_suffixes=[".parquet", ".json", ".jsonl", ".csv"],
                         operation="dataset-import")
if lease is None or lease_expired(lease):
    re_prompt_user()

Type guard

def is_fresh_lease(lease: str) -> TypeGuard[str]:
    try:
        return verify_native_path_lease(lease, operation="dataset-import",
                                        expected_kind="dataset",
                                        expected_path_type="file") is not None
    except NativePathLeaseError:
        return False

Try / catch

try:
    upload_dataset(client, native_path_lease=lease)
except HTTPStatusError as e:
    if e.response.status_code == 400:
        lease = re_mint_lease()  # detail text says which check failed; fresh lease fixes TTL issues
        retry_once_with(lease)
    else:
        raise

Prevention

When it happens

Trigger: Reusing an old lease after expiry; presenting a lease minted for a different operation or a directory instead of a file; lease path pointing at a file with a non-allowed extension; lease signed for a different path than the one re-submitted.

Common situations: User sat on the import dialog past the lease TTL; app state restored from an old session replaying a stale lease; the native file was renamed or re-saved as another format between lease grant and import.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/d00d598e526a8fb1. Report an issue: GitHub.