{"record":{"id":"6756881ee130f032","repo":"cayleygraph/cayley","slug":"unexpected-hash-length-d","errorCode":null,"errorMessage":"unexpected hash length: %d","messagePattern":"unexpected hash length: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graph/sql/quadstore.go","lineNumber":91,"sourceCode":"\tif !h.Valid() {\n\t\treturn nil\n\t}\n\treturn []byte(h.ValueHash[:])\n}\nfunc (h *NodeHash) Scan(src interface{}) error {\n\tif src == nil {\n\t\t*h = NodeHash{}\n\t\treturn nil\n\t}\n\tb, ok := src.([]byte)\n\tif !ok {\n\t\treturn fmt.Errorf(\"cannot scan %T to NodeHash\", src)\n\t}\n\tif len(b) == 0 {\n\t\t*h = NodeHash{}\n\t\treturn nil\n\t} else if len(b) != quad.HashSize {\n\t\treturn fmt.Errorf(\"unexpected hash length: %d\", len(b))\n\t}\n\tcopy(h.ValueHash[:], b)\n\treturn nil\n}\n\nfunc HashOf(s quad.Value) NodeHash {\n\treturn NodeHash{refs.HashOf(s)}\n}\n\ntype QuadHashes struct {\n\trefs.QuadHash\n}\n\ntype QuadStore struct {\n\tdb      *sql.DB\n\topt     *Optimizer\n\tflavor  Registration\n\tids     *lru.Cache","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/cayleygraph/cayley/blob/81dcd7d73e45136bc0d01802a8ba4685d8a533eb/graph/sql/quadstore.go#L73-L109","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Verify the column actually stores raw binary hashes of the expected fixed length.","Rebuild the schema with the store's Init so hashes are stored raw at the correct size.","If data is hex-encoded, decode it to raw bytes before/instead of scanning directly into NodeHash.","Check the SELECT column list to make sure the right column maps to NodeHash."],"exampleFix":"// before\nvar raw []byte\nrows.Scan(&raw) // 64-byte hex string bytes\n// after\nvar hexStr string\nrows.Scan(&hexStr)\nraw, _ := hex.DecodeString(hexStr)\nvar h NodeHash\ncopy(h.ValueHash[:], raw)","handlingStrategy":"validation","validationCode":"// validate hash length before trusting stored data\n// SELECT OCTET_LENGTH(hash_col) FROM t LIMIT 1; must equal quad.HashSize","typeGuard":null,"tryCatchPattern":"var h NodeHash\nif err := rows.Scan(&h); err != nil {\n    if strings.Contains(err.Error(), \"unexpected hash length\") {\n        // decode hex or re-migrate the column to raw fixed-size hashes\n    }\n}","preventionTips":["Store hashes raw binary at the exact expected size, not hex-encoded.","Verify column length after schema migrations.","Map SELECT columns carefully so only hash columns scan into NodeHash."],"tags":["sql","scan","hash","data-corruption"],"backgroundTag":"invalid-data-length","analyzedSha":"81dcd7d73e45136bc0d01802a8ba4685d8a533eb","analyzedAt":"2026-09-06T06:14:12.358Z","contentChangedAt":"2026-09-06T06:14:12.358Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}