{"record":{"id":"4b0b4d1351c54327","repo":"mgth/LittleBigMouse","slug":"payload-was-protected-with-scheme-unreadable-on-this-system","errorCode":null,"errorMessage":"Payload was protected with '{scheme}', unreadable on this system.","messagePattern":"Payload was protected with '(.+?)', unreadable on this system\\.","errorType":"exception","errorClass":"CryptographicException","httpStatus":null,"severity":"error","filePath":"LittleBigMouse.Plugins/LittleBigMouse.Plugins.Core/SecretProtector.cs","lineNumber":120,"sourceCode":"\n            case AesGcmScheme:\n                if (payload.Length < NonceLength + TagLength)\n                    throw new CryptographicException(\"Protected payload is truncated.\");\n\n                var plain = new byte[payload.Length - NonceLength - TagLength];\n                using (var aes = new AesGcm(ReadKey() ?? throw new CryptographicException(\n                           $\"No key at {_keyFilePath} to read this payload with.\"), TagLength))\n                {\n                    aes.Decrypt(\n                        payload.AsSpan(0, NonceLength),\n                        payload.AsSpan(NonceLength + TagLength),\n                        payload.AsSpan(NonceLength, TagLength),\n                        plain);\n                }\n                return Encoding.UTF8.GetString(plain);\n\n            default:\n                throw new CryptographicException(\n                    $\"Payload was protected with '{scheme}', unreadable on this system.\");\n        }\n    }\n\n    byte[] GetOrCreateKey()\n    {\n        lock (_keyLock)\n        {\n            return _key ??= ReadKeyLocked() ?? CreateKeyLocked();\n        }\n    }\n\n    byte[]? ReadKey()\n    {\n        lock (_keyLock)\n        {\n            return _key ??= ReadKeyLocked();\n        }","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/mgth/LittleBigMouse/blob/7a42f01d47d99d223b8ee33ba4019af82adf1c48/LittleBigMouse.Plugins/LittleBigMouse.Plugins.Core/SecretProtector.cs#L102-L138","documentation":"Envelopes are self-describing ('LBM1.<scheme>.<base64>'). Unprotect only understands 'dpapi' (on Windows) and 'aesgcm' (anywhere); any other scheme hits this default case and throws a CryptographicException naming the scheme. It exists so a payload carried to a machine that cannot read it fails loudly instead of silently decoding to garbage.","triggerScenarios":"Calling Unprotect on an envelope whose scheme token is neither 'dpapi' nor 'aesgcm' — e.g. a 'dpapi' envelope from a Windows profile opened on Linux/macOS, an envelope produced by a newer version with an added scheme, or a hand-edited/corrupted scheme field.","commonSituations":"Syncing or copying the config directory between Windows and Unix machines; restoring a Windows-encrypted settings file on Linux; upgrading from a future version that introduced a new scheme and then downgrading; manual editing of the envelope string.","solutions":["Re-create the secret on this machine: delete the stored envelope and re-enter/re-pair so Protect seals it with a scheme this system supports.","If it is a dpapi envelope, open the data file on Windows (or with the same user account on Windows) and migrate the value to clear text or re-protect it there.","If caused by a version downgrade, upgrade back to the version that wrote the envelope.","Check the envelope string is intact (starts with 'LBM1.' followed by dpapi or aesgcm) in case the file was corrupted or truncated in transfer."],"exampleFix":"// before\nvar token = protector.Unprotect(envelopeFromSyncedProfile); // dpapi envelope on Linux\n// after\nif (envelope.StartsWith(\"LBM1.dpapi.\") && !OperatingSystem.IsWindows())\n    token = RePairDevice(); // scheme unreadable here — obtain it fresh\nelse\n    token = protector.Unprotect(envelope);","handlingStrategy":"type-guard","validationCode":"static bool SchemeSupportedHere(string envelope) =>\n    !SecretProtector.IsProtected(envelope) ||\n    (envelope.StartsWith(\"LBM1.dpapi.\") && OperatingSystem.IsWindows()) ||\n    envelope.StartsWith(\"LBM1.aesgcm.\");","typeGuard":"static bool IsReadableOnThisSystem(string envelope)\n{\n    if (!SecretProtector.IsProtected(envelope)) return true; // clear text\n    var scheme = envelope[5..envelope.IndexOf('.')];\n    return scheme switch\n    {\n        \"dpapi\" => OperatingSystem.IsWindows(),\n        \"aesgcm\" => true,\n        _ => false\n    };\n}","tryCatchPattern":"try { return protector.Unprotect(envelope); }\ncatch (CryptographicException ex) when (ex.Message.Contains(\"unreadable on this system\"))\n{ return ReCreateSecret(); /* scheme unsupported here */ }","preventionTips":["Do not sync secret-bearing config files between Windows and Unix profiles; re-pair per platform.","Before restoring a backup on a different OS, strip or migrate protected envelopes first.","Pin major versions: envelopes written by a newer scheme cannot be read after a downgrade.","Prefer clear-text migration on export (with user consent) over moving dpapi envelopes cross-platform."],"tags":["cryptography","platform-compatibility","dpapi","scheme-mismatch"],"backgroundTag":"unsupported-platform","analyzedSha":"7a42f01d47d99d223b8ee33ba4019af82adf1c48","analyzedAt":"2026-09-16T00:35:00.514Z","contentChangedAt":"2026-09-16T00:35:00.514Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}