HKUDS/Vibe-Trading · error · ValueError

ModelArtifact.input_hash must be a 64-character sha256 hex d

Error message

ModelArtifact.input_hash must be a 64-character sha256 hex digest, got {self.input_hash!r}

What it means

ModelArtifact validates that input_hash is exactly a 64-character lowercase hex string — the shape of a sha256 digest produced by compute_input_hash. Anything else (short hash, uppercase, 'md5', None) is rejected so artifacts can be reliably keyed and compared by hash.

Source

Thrown at agent/src/quantlib/valuation/artifact.py:263

    excluded: tuple[str, ...]
    warnings: tuple[str, ...]

    def __post_init__(self) -> None:
        """Check the artifact's own invariants.

        Raises:
            ValueError: If ``model_name`` is not one of :data:`_MODEL_NAMES`,
                or ``input_hash`` is not a 64-character hex sha256 digest.
        """
        if self.model_name not in _MODEL_NAMES:
            raise ValueError(
                f"ModelArtifact.model_name must be one of {_MODEL_NAMES}, "
                f"got {self.model_name!r}"
            )
        if len(self.input_hash) != 64 or any(
            c not in "0123456789abcdef" for c in self.input_hash
        ):
            raise ValueError(
                f"ModelArtifact.input_hash must be a 64-character sha256 hex "
                f"digest, got {self.input_hash!r}"
            )


@dataclass(frozen=True)
class FieldChange:
    """One field that differs between two artifacts' inputs or outputs.

    Attributes:
        path: The dotted/bracket path that changed.
        old: The baseline artifact's value at ``path``.
        new: The updated artifact's value at ``path``.
        delta: ``new - old`` when both are numbers (and neither is a
            ``bool``); ``None`` otherwise (e.g. a string or boolean field, or
            a field that changed type).
    """

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use the project's compute_input_hash(...) to produce the digest.
  2. If hashing yourself: hashlib.sha256(...).hexdigest() gives exactly 64 lowercase hex chars.
  3. Never truncate or re-case the digest before storing it.

Example fix

// before
ModelArtifact(input_hash=hashlib.md5(payload).hexdigest(), ...)
// after
from quantlib.valuation.artifact import compute_input_hash
ModelArtifact(input_hash=compute_input_hash(inputs), ...)
Defensive patterns

Strategy: type-guard

Validate before calling

import re
assert isinstance(input_hash, str) and re.fullmatch(r"[0-9a-f]{64}", input_hash), \
    f"input_hash must be 64-char sha256 hex, got {input_hash!r}"

Type guard

import re
def is_sha256_hex(s) -> bool:
    return isinstance(s, str) and re.fullmatch(r"[0-9a-f]{64}", s) is not None

Prevention

When it happens

Trigger: ModelArtifact(input_hash=hashlib.md5(...).hexdigest(), ...) (32 chars); passing an uppercase digest, a truncated hash, or a placeholder string; passing None and hitting the length check behavior.

Common situations: Swapping hash algorithms during a refactor; hand-building artifacts in tests with dummy hashes like 'abc'; feeding a non-hash id field.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/80473b32542704db. Report an issue: GitHub.