Comfy-Org/ComfyUI · error · HashMismatchError

HASH_MISMATCH

HASH_MISMATCH

Error message

Uploaded file hash does not match provided hash.

What it means

Raised by the asset upload pipeline when the BLAKE3 hash computed over the received temp file ('blake3:<digest>') does not equal the client-declared expected_hash (after strip+lowercase normalization). This is end-to-end integrity verification: the bytes that landed on disk differ from the bytes the sender hashed, so the upload is refused with HASH_MISMATCH instead of being recorded under a false hash.

Source

Thrown at app/assets/services/ingest.py:488

    name: str | None = None,
    tags: list[str] | None = None,
    user_metadata: dict | None = None,
    client_filename: str | None = None,
    owner_id: str = "",
    expected_hash: str | None = None,
    mime_type: str | None = None,
    preview_id: str | None = None,
) -> UploadResult:
    try:
        digest, _ = hashing.compute_blake3_hash(temp_path)
    except ImportError as e:
        raise DependencyMissingError(str(e))
    except Exception as e:
        raise RuntimeError(f"failed to hash uploaded file: {e}")
    asset_hash = "blake3:" + digest

    if expected_hash and asset_hash != expected_hash.strip().lower():
        raise HashMismatchError("Uploaded file hash does not match provided hash.")

    with create_session() as session:
        existing = get_asset_by_hash(session, asset_hash=asset_hash)

    if existing is not None:
        # Once content is already known, duplicate byte uploads are treated as
        # reference-only creation. Request tags are labels only here: do not
        # require upload destination tags, do not move bytes, and do not
        # synthesize path-derived classification or uploaded provenance.
        with contextlib.suppress(Exception):
            if temp_path and os.path.exists(temp_path):
                os.remove(temp_path)

        display_name = _sanitize_filename(name or client_filename, fallback=digest)
        result = _register_existing_asset(
            asset_hash=asset_hash,
            name=display_name,
            user_metadata=user_metadata or {},

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Re-hash the exact file bytes with BLAKE3 immediately before upload and send 'blake3:' + lowercase hex digest.
  2. Verify the file wasn't modified after hashing (disable sync/editors; hash and upload in one step).
  3. Retry the upload on a clean connection; a truncated body will never match.
  4. Omit expected_hash entirely if you don't need integrity verification — the server computes its own hash regardless.

Example fix

# before
expected = 'sha256:' + hashlib.sha256(data).hexdigest()

# after
import blake3
expected = 'blake3:' + blake3.blake3(file_bytes).hexdigest()
Defensive patterns

Strategy: validation

Validate before calling

import blake3

def make_expected_hash(path) -> str:
    h = blake3.blake3()
    with open(path, 'rb') as f:
        for chunk in iter(lambda: f.read(1 << 20), b''):
            h.update(chunk)
    return 'blake3:' + h.hexdigest()

Type guard

import re
EXPECTED_HASH_RE = re.compile(r'^blake3:[0-9a-f]{64}$')
def is_valid_expected_hash(v) -> bool:
    return bool(v) and EXPECTED_HASH_RE.match(v.strip().lower()) is not None

Try / catch

try:
    upload(path, expected_hash=make_expected_hash(path))
except HashMismatchError:
    # re-hash and retry once; persistent mismatch means local file changed
    upload(path, expected_hash=make_expected_hash(path))

Prevention

When it happens

Trigger: POST an asset upload with an `expected_hash` header/field of 'blake3:abc...' while the multipart body contains different bytes — truncated transfer, a mutated file between hashing and sending, wrong hash algorithm (e.g. SHA-256 hex passed as blake3), or an uppercase/unprefixed hash string that doesn't match after normalization.

Common situations: Client hashes with sha256 instead of blake3; file modified (or re-saved by an editor/cloud sync) between hashing and upload; partial upload due to connection reset; hash copied with whitespace or missing 'blake3:' prefix; case mismatch in the digest.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/51c5a74ded664904. Report an issue: GitHub.