{"record":{"id":"b882407051f6f5bc","repo":"kopia/kopia","slug":"invalid-data-too-short","errorCode":null,"errorMessage":"invalid data - too short","messagePattern":"invalid data - too short","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/hmac/hmac.go","lineNumber":29,"sourceCode":"\t\"github.com/kopia/kopia/internal/gather\"\n)\n\n// Append computes HMAC-SHA256 checksum for a given block of bytes and appends it.\nfunc Append(input gather.Bytes, secret []byte, output *gather.WriteBuffer) {\n\th := hmac.New(sha256.New, secret)\n\n\tinput.WriteTo(output) //nolint:errcheck\n\tinput.WriteTo(h)      //nolint:errcheck\n\n\tvar hash [sha256.Size]byte\n\n\toutput.Write(h.Sum(hash[:0])) //nolint:errcheck\n}\n\n// VerifyAndStrip verifies that given block of bytes has correct HMAC-SHA256 checksum and strips it.\nfunc VerifyAndStrip(input gather.Bytes, secret []byte, output *gather.WriteBuffer) error {\n\tif input.Length() < sha256.Size {\n\t\treturn errors.New(\"invalid data - too short\")\n\t}\n\n\tp := input.Length() - sha256.Size\n\n\th := hmac.New(sha256.New, secret)\n\tr := input.Reader()\n\n\tif _, err := io.CopyN(io.MultiWriter(h, output), r, int64(p)); err != nil {\n\t\treturn errors.Wrap(err, \"error hashing\")\n\t}\n\n\tvar sigBuf, actualSignature [sha256.Size]byte\n\n\tvalidSignature := h.Sum(sigBuf[:0])\n\n\tn, err := r.Read(actualSignature[:])\n\tif err != nil || n != sha256.Size {\n\t\treturn errors.Wrap(err, \"error reading signature\")","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/kopia/kopia/blob/82495e54b584c1ef6073c9e1be048f57f8aef078/internal/hmac/hmac.go#L11-L47","documentation":"hmac.VerifyAndStrip expects input whose trailing sha256.Size (32) bytes are an HMAC-SHA256 signature appended by the writer. If the input is shorter than 32 bytes there cannot be a signature, so it fails immediately with 'invalid data - too short'.","triggerScenarios":"Calling VerifyAndStrip (via hmac.Verify or when reading blobs from cache) with a buffer shorter than 32 bytes — e.g. an empty/truncated cache entry, a ciphertext blob that lost its trailing signature, or reading the wrong file/offset.","commonSituations":"Corrupted or partially written cache files on disk; a changed storage format or version mismatch where the HMAC trailer is absent; misconfigured cache directory containing foreign files.","solutions":["Check input.Length() >= sha256.Size before calling VerifyAndStrip.","Delete the corrupted cache entry so it is re-fetched/regenerated.","Verify the data producer actually appends the HMAC trailer (same kopia format version)."],"exampleFix":"// before\nerr := hmac.VerifyAndStrip(data, secret, out)\n// after\nif data.Length() < sha256.Size {\n    return errors.New(\"cache entry truncated, refetching\")\n}\nerr := hmac.VerifyAndStrip(data, secret, out)","handlingStrategy":"validation","validationCode":"if data.Length() < sha256.Size {\n    return errors.New(\"blob too short to contain HMAC trailer\")\n}\nreturn hmac.VerifyAndStrip(data, secret, out)","typeGuard":null,"tryCatchPattern":"err := hmac.VerifyAndStrip(data, secret, out)\nif err != nil && strings.Contains(err.Error(), \"too short\") {\n    // treat as corrupt cache entry: delete and refetch\n    return refetchBlob(id)\n}","preventionTips":["Check blob length >= 32 before verifying cached data.","Ensure writers append the HMAC trailer in the same format version.","Monitor cache directories for truncated files after crashes."],"tags":["go","hmac","integrity"],"backgroundTag":"checksum-mismatch","analyzedSha":"82495e54b584c1ef6073c9e1be048f57f8aef078","analyzedAt":"2026-09-07T20:35:21.689Z","contentChangedAt":"2026-09-07T20:35:21.689Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}