{"record":{"id":"f7522c241063af22","repo":"restic/restic","slug":"unable-to-create-cipher-v-f7522c","errorCode":null,"errorMessage":"unable to create cipher: %v","messagePattern":"unable to create cipher: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/repository/debug.go","lineNumber":278,"sourceCode":"\tif err != nil {\n\t\tpanic(\"all go routines can only return nil\")\n\t}\n\n\tif !found {\n\t\tprinter.S(\"\\n        blob could not be repaired\")\n\t}\n\treturn fixed\n}\n\nfunc decryptUnsigned(k *crypto.Key, buf []byte) []byte {\n\t// strip signature at the end\n\tl := len(buf)\n\tnonce, ct := buf[:16], buf[16:l-16]\n\tout := make([]byte, len(ct))\n\n\tc, err := aes.NewCipher(k.EncryptionKey[:])\n\tif err != nil {\n\t\tpanic(fmt.Sprintf(\"unable to create cipher: %v\", err))\n\t}\n\te := cipher.NewCTR(c, nonce)\n\te.XORKeyStream(out, ct)\n\n\treturn out\n}\n\nfunc loadBlobs(ctx context.Context, opts ExaminePackOptions, repo *Repository, packID restic.ID, list pack.Blobs, printer restic.Printer) error {\n\tdec, err := zstd.NewReader(nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tpackData, err := repo.LoadRaw(ctx, restic.PackFile, packID)\n\t// allow processing broken pack files\n\tif packData == nil {\n\t\treturn err\n\t}","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/restic/restic/blob/a80be1478a4c537f8396e0db2b05120aa78f11e0/internal/repository/debug.go#L260-L296","documentation":"decryptUnsigned is a debug/repair helper (loadBlobs path behind 'restic repair pack') that AES-CTR decrypts pack data using k.EncryptionKey. aes.NewCipher fails only for keys not 16/24/32 bytes, and restic uses 32-byte keys exclusively, so this panic means the Key passed into the repair path has a wrong-size encryption key. It signals key corruption or a wrongly constructed crypto.Key rather than damaged repository data.","triggerScenarios":"Running 'restic repair pack' when the in-memory crypto.Key is malformed; embedding code passing a hand-built Key into the examine/repair helpers; memory corruption altering the key slice length.","commonSituations":"Custom tooling that reuses restic's internal repair APIs with manually assembled keys; sporadic hardware-induced corruption.","solutions":["Ensure the Key comes from the repository's key unlocking path (crypto.KDF via restic keys), never constructed by hand","Validate k.Valid() before invoking repair commands","If spontaneous, test RAM and disk health"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if !k.Valid() {\n\treturn errors.New(\"invalid crypto key for repair path\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pass only keys obtained from repository unlocking into repair helpers","Validate the key once at session start, not per blob"],"tags":["crypto","aes","repair","key","panic","go"],"backgroundTag":null,"analyzedSha":"a80be1478a4c537f8396e0db2b05120aa78f11e0","analyzedAt":"2026-08-15T15:30:29.928Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}