{"record":{"id":"2ef536fc5e4d56d2","repo":"restic/restic","slug":"error-converting-bytes-to-security-descriptor-w","errorCode":null,"errorMessage":"error converting bytes to security descriptor: %w","messagePattern":"error converting bytes to security descriptor: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/fs/sd_windows.go","lineNumber":77,"sourceCode":"\t}\n\n\tsdBytes, err := securityDescriptorStructToBytes(sd)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"convert security descriptor to bytes failed: %w\", err)\n\t}\n\treturn &sdBytes, nil\n}\n\n// setSecurityDescriptor sets the SecurityDescriptor for the file at the specified path.\n// This needs admin permissions or SeRestorePrivilege, SeSecurityPrivilege and SeTakeOwnershipPrivilege\n// for setting the full SD.\n// If there are no admin permissions/required privileges, only the DACL from the SD can be set and\n// owner and group will be set based on the current user.\nfunc setSecurityDescriptor(filePath string, securityDescriptor *[]byte) error {\n\t// Set the security descriptor on the file\n\tsd, err := securityDescriptorBytesToStruct(*securityDescriptor)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error converting bytes to security descriptor: %w\", err)\n\t}\n\n\towner, _, err := sd.Owner()\n\tif err != nil {\n\t\t//Do not set partial values.\n\t\towner = nil\n\t}\n\tgroup, _, err := sd.Group()\n\tif err != nil {\n\t\t//Do not set partial values.\n\t\tgroup = nil\n\t}\n\tdacl, _, err := sd.DACL()\n\tif err != nil {\n\t\t//Do not set partial values.\n\t\tdacl = nil\n\t}\n\tsacl, _, err := sd.SACL()","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/restic/restic/blob/a80be1478a4c537f8396e0db2b05120aa78f11e0/internal/fs/sd_windows.go#L59-L95","documentation":"During restore, setSecurityDescriptor first converts the stored descriptor bytes back to a struct with securityDescriptorBytesToStruct; this error wraps that conversion failing. The bytes come from the snapshot's GenericAttributes, so failure means the stored blob is not a valid self-relative security descriptor. This points to snapshot data corruption or an encoding mismatch rather than a rights problem (rights are checked later during the set calls).","triggerScenarios":"The SecurityDescriptor blob in the snapshot is truncated or bit-flipped (repo corruption, failing disk); the snapshot was created by a restic version or tool that stored the field differently; the raw bytes pass JSON decoding but fail ConvertStringSecurityDescriptorToSecurityDescriptor/LocalAlloc validation.","commonSituations":"Restoring from a repo on deteriorating media without prior check runs; snapshots migrated between repos with faulty tooling; very old snapshots after format evolution.","solutions":["Run `restic check --read-data` on the repository to detect corruption.","Verify which restic version created the snapshot (`restic snapshots --json`) and restore with a current build.","If only ACLs are affected, restore without them and re-apply permissions from a known-good source (icacls /restore).","If corruption is confirmed, restore from an older healthy snapshot."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import \"golang.org/x/sys/windows\"\n\n// validate stored SD bytes before restore-time conversion:\nfunc validSecurityDescriptorBytes(b []byte) bool {\n\tif len(b) == 0 {\n\t\treturn false\n\t}\n\t// self-relative SD must start with revision 1 and the SE_SELF_RELATIVE (0x8000) flag\n\treturn b[0] == 1 && b[2] == 0x80 && b[3] == 0x00\n}","typeGuard":null,"tryCatchPattern":"if err := setSecurityDescriptor(path, sdBytes); err != nil {\n\tif strings.Contains(err.Error(), \"converting bytes to security descriptor\") {\n\t\t// stored blob invalid: corruption indicator — run restic check, skip ACL for this file\n\t\twarnf(\"stored ACL for %s is invalid: %v\", path, err)\n\t} else {\n\t\twarnf(\"ACL restore for %s: %v\", path, err)\n\t}\n}","preventionTips":["Run `restic check --read-data` periodically to catch corruption early.","Restore with a restic version compatible with the snapshot's creator.","Keep a secondary copy of critical repos on healthy storage."],"tags":["go","windows","security-descriptor","corruption","restore","validation"],"backgroundTag":null,"analyzedSha":"a80be1478a4c537f8396e0db2b05120aa78f11e0","analyzedAt":"2026-08-15T15:30:29.928Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}