cayleygraph/cayley · error

unexpected hash length: %d

Error message

unexpected hash length: %d

What it means

NodeHash.Scan checks that the []byte delivered by the driver has exactly quad.HashSize bytes before copying it into the fixed-size hash array. A different length means the column contains truncated, padded, or incorrectly encoded hash data.

Source

Thrown at graph/sql/quadstore.go:91

	if !h.Valid() {
		return nil
	}
	return []byte(h.ValueHash[:])
}
func (h *NodeHash) Scan(src interface{}) error {
	if src == nil {
		*h = NodeHash{}
		return nil
	}
	b, ok := src.([]byte)
	if !ok {
		return fmt.Errorf("cannot scan %T to NodeHash", src)
	}
	if len(b) == 0 {
		*h = NodeHash{}
		return nil
	} else if len(b) != quad.HashSize {
		return fmt.Errorf("unexpected hash length: %d", len(b))
	}
	copy(h.ValueHash[:], b)
	return nil
}

func HashOf(s quad.Value) NodeHash {
	return NodeHash{refs.HashOf(s)}
}

type QuadHashes struct {
	refs.QuadHash
}

type QuadStore struct {
	db      *sql.DB
	opt     *Optimizer
	flavor  Registration
	ids     *lru.Cache

View on GitHub (pinned to 81dcd7d73e)

Solutions

  1. Verify the column actually stores raw binary hashes of the expected fixed length.
  2. Rebuild the schema with the store's Init so hashes are stored raw at the correct size.
  3. If data is hex-encoded, decode it to raw bytes before/instead of scanning directly into NodeHash.
  4. Check the SELECT column list to make sure the right column maps to NodeHash.

Example fix

// before
var raw []byte
rows.Scan(&raw) // 64-byte hex string bytes
// after
var hexStr string
rows.Scan(&hexStr)
raw, _ := hex.DecodeString(hexStr)
var h NodeHash
copy(h.ValueHash[:], raw)
Defensive patterns

Strategy: validation

Validate before calling

// validate hash length before trusting stored data
// SELECT OCTET_LENGTH(hash_col) FROM t LIMIT 1; must equal quad.HashSize

Try / catch

var h NodeHash
if err := rows.Scan(&h); err != nil {
    if strings.Contains(err.Error(), "unexpected hash length") {
        // decode hex or re-migrate the column to raw fixed-size hashes
    }
}

Prevention

When it happens

Trigger: Scanning a query result into NodeHash where the hash column holds bytes of length != quad.HashSize (e.g. hex-encoded hash twice the size, empty-adjacent truncation, wrong column scanned).

Common situations: Hashes stored hex-encoded instead of raw binary; schema written by a different library version with different hash sizes; SELECT column order mismatch feeding a non-hash column into NodeHash.

Related errors


AI-assisted analysis of cayleygraph/cayley@81dcd7d73e (2026-09-06). Data as JSON: /api/errors/6756881ee130f032. Report an issue: GitHub.