unslothai/unsloth · error · HTTPException
Native path grant is required.
Error message
Native path grant is required.
What it means
When attaching a file by native path (desktop drag-drop), the backend must first verify a signed native-path lease via verify_native_path_lease() with operation='attach', kind='attachment', path_type='file', and suffixes limited to config.UPLOAD_EXTS. Any NativePathLeaseError — including 'Native path grant is required.' when the lease token is absent, malformed, expired, or fails verification — surfaces as HTTP 400 with the lease error's text.
Source
Thrown at studio/backend/routes/rag.py:177
def _save_native_path_upload(lease: str) -> tuple[str, str]:
"""Persist a desktop drop; returns (stored_path, filename).
The webview never gets to name a path directly: Rust signs the path it saw and we
re-verify + re-stat that grant here before reading a byte.
"""
from utils.native_path_leases import NativePathLeaseError, verify_native_path_lease
try:
grant = verify_native_path_lease(
lease,
operation = "attach",
expected_kind = "attachment",
expected_path_type = "file",
allowed_suffixes = sorted(config.UPLOAD_EXTS),
)
except NativePathLeaseError as exc:
raise HTTPException(status_code = 400, detail = str(exc)) from exc
filename = _sanitize_filename(grant.canonical_path.name)
try:
with open(grant.canonical_path, "rb") as source:
return _persist_upload_stream(
source,
filename,
empty_detail = "Dropped file is empty.",
)
except OSError as exc:
raise HTTPException(status_code = 400, detail = "Dropped file could not be read.") from exc
def _resolve_document_upload(
file: UploadFile | None, native_path_lease: str | None
) -> tuple[str, str]:
if native_path_lease:
return _save_native_path_upload(native_path_lease)View on GitHub (pinned to 203007d190)
Solutions
- Request a fresh lease from the native-path lease issuer for the exact file right before upload and pass it unchanged.
- Confirm the lease is for operation 'attach', kind 'attachment', path type 'file', and the file's extension is in config.UPLOAD_EXTS.
- Do not cache or reuse leases across sessions; re-request after expiry errors.
Example fix
// before
body: { nativePathLease: filePath } // raw path, no lease -> 400
// after
const lease = await bridge.requestLease(filePath, { kind: 'attachment', operation: 'attach' });
body: { nativePathLease: lease.token } Defensive patterns
Strategy: validation
Validate before calling
const lease = await bridge.requestLease(path, { kind: 'attachment', operation: 'attach', pathType: 'file' });
if (!lease?.token) throw new Error('no lease granted'); Try / catch
if (res.status === 400 && /Native path grant/.test(detail)) { re_request_lease(path); } Prevention
- Never send raw filesystem paths; always go through the lease broker.
- Use the lease immediately — they expire; re-request on 400 rather than caching.
- Match lease kind/operation/path_type to the endpoint you are calling.
When it happens
Trigger: Calling the attach endpoint with a native_path_lease that is missing, empty, has a bad signature, names the wrong operation/kind/path-type, points at a file with a disallowed extension, or was issued for a different path or after expiry.
Common situations: Frontend sends the raw path instead of requesting a lease from the desktop bridge; lease expired between selection and upload; replaying an old lease after the file was replaced; mismatch between the lease's granted kind and the endpoint's expectation.
Related errors
- Dropped file could not be read.
- Native folder grant has no stable identity.
- Unsupported file type '{ext}'. Allowed: {sorted(config.UPLOA
- Uploaded file is empty.
- No file was provided.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/730eafcca1e0714c.
Report an issue: GitHub.