unslothai/unsloth · error · RuntimeError
{spec.name} source revision must be a lowercase full Git com
Error message
{spec.name} source revision must be a lowercase full Git commit What it means
First check in ensure_pinned_source: spec.revision must be a full 40-char lowercase hex Git commit SHA — it must match _REVISION_PATTERN and equal its own .lower() (i.e. no uppercase). The library pins immutable commits, not mutable refs, and normalizes nothing for you: the check runs before any cache lookup or download.
Source
Thrown at studio/backend/utils/third_party_source.py:777
if hashlib.sha256(destination_file.read_bytes()).hexdigest() != expected_digest:
raise RuntimeError(f"{spec.name} source changed while preparing its runtime")
for relative, content in _generated_file_contents(spec).items():
destination_file = staging / relative
destination_file.parent.mkdir(parents = True, exist_ok = True)
destination_file.write_bytes(content)
if not _valid_runtime(staging, spec, checkout):
raise RuntimeError(f"The prepared {spec.name} runtime failed integrity validation")
_replace_owned_directory(staging, runtime)
finally:
_remove_owned_path(workspace)
def ensure_pinned_source(
spec: PinnedSource, *, legacy_sources: tuple[Path | str, ...] = ()
) -> Path:
revision = spec.revision.lower()
if _REVISION_PATTERN.fullmatch(revision) is None or revision != spec.revision:
raise RuntimeError(f"{spec.name} source revision must be a lowercase full Git commit")
for digest in (spec.source_tree_digest, spec.runtime_tree_digest):
if digest is not None and _SHA256_PATTERN.fullmatch(digest) is None:
raise RuntimeError(f"{spec.name} source digest must be a lowercase SHA-256")
if (spec.source_tree_digest is None) != (spec.runtime_tree_digest is None):
raise RuntimeError(f"{spec.name} source and runtime digests must be configured together")
parent = cache_root() / "third-party-sources" / spec.name
version_root = parent / revision
checkout = version_root / "source"
runtime = version_root / "runtime-v1"
if _valid_runtime(runtime, spec):
return runtime.resolve()
version_root.mkdir(parents = True, exist_ok = True)
try:
with FileLock(str(parent / ".install.lock"), timeout = 300):
if _valid_runtime(runtime, spec):
return runtime.resolve()View on GitHub (pinned to 203007d190)
Solutions
- Resolve the ref to a full commit: git rev-parse <tag>^{commit} and use that 40-char lowercase SHA as revision
- Normalize before constructing the spec: revision=revision.strip().lower() and assert 40 hex chars
- If you intended a floating ref, that is unsupported — pins must be immutable commits
Example fix
# before PinnedSource(name="foo", package="foo", revision="v1.2.3", ...) # after sha = subprocess.check_output(["git", "ls-remote", url, "refs/tags/v1.2.3"]).split()[0].decode() PinnedSource(name="foo", package="foo", revision=sha.lower(), ...)
Defensive patterns
Strategy: validation
Validate before calling
import re
_REVISION_PATTERN = re.compile(r"[0-9a-f]{40}")
assert _REVISION_PATTERN.fullmatch(spec.revision), (
f"revision {spec.revision!r} must be a full 40-char lowercase hex commit SHA"
) Type guard
import re
def is_full_commit_sha(revision: object) -> bool:
return isinstance(revision, str) and re.fullmatch(r"[0-9a-f]{40}", revision) is not None Prevention
- Always resolve tags/branches via git rev-parse <ref>^{commit} before writing them into a pin
- Validate pins in config tests: revision matches ^[0-9a-f]{40}$ and both digests are paired 64-char lowercase hex
When it happens
Trigger: Passing revision as a tag/branch name ('v1.2.3', 'main'), a short SHA ('1a2b3c4'), an uppercase SHA ('1A2B...'), or a string with whitespace. The lowercase(pattern-match) + equality-with-original construction rejects any uppercase input explicitly.
Common situations: Copy-pasting a tag instead of the commit it resolves to; tooling that emits short SHAs; UIs uppercasing hex; config files generated from git describe output.
Related errors
- The pinned {spec.name} source archive is not configured
- Add a Provider connection block before running this recipe.
- Unsupported attention_backend '{value}'. Use one of: {', '.j
- Unsupported transformer_cache '{value}'. Use one of: off, au
- too many extra llama-server args (limit {MAX_EXTRA_ARG_TOKEN
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/31632cda06f7361e.
Report an issue: GitHub.